今天看call/apply/bind的区别时,想起当初用react时,render中绑定事件总要把类中的方法bind(this),当初时一知半解,这次一定要弄懂原因
首先我们看react官网说法:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
我们经常用到的onClick={this.handleClick},需要在contructor显示绑定this,或者用箭头函数定义handleClick,则不需要绑定this,那么这是为什么呢?
实际上这不是react的问题,是javaScript的函数工作原理造成的。
我翻阅MDN上关于class类的描述,找到了原理 MDN链接:
在严格模式下通过this传递给一个函数的值不会被强制转换为一个对象。对一个普通的函数来说,this总会是一个对象:不管调用时this它本来就是一个对象;还是用布尔值,字符串或者数字调用函数时函数里面被封装成对象的this;还是使用undefined或者null调用函数式this代表的全局对象(使用call, apply或者bind方法来指定一个确定的this)。这种自动转化为对象的过程不仅是一种性能上的损耗,同时在浏览器中暴露出全局对象也会成为安全隐患,因为全局对象提供了访问那些所谓安全的JavaScript环境必须限制的功能的途径。所以对于一个开启严格模式的函数,指定的this不再被封装为对象,而且如果没有指定this的话它值是undefined:
最后一句话,严格模式下,this如果没有指定的话就是undefined。
当然,这里说的是普通函数,箭头函数的this不会为undefied。为什么箭头函数的this正常呢,因为箭头函数有几个特点,其中: 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
请大声朗读三遍,也就是说,箭头函数定义时this已经指向了当前类,就不会出现普通函数this没有指向的问题。
总结
综上, react bind this问题,根本原因是 :class 类 默认是严格模式,普通函数的this如果不指定就会指向undefined,要在constructor函数中绑定或将类方法写为箭头函数。所以跟react无关,是因为js函数工作原理。