React 中的 this
一、为事件处理函数绑定上 this
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')
);
上面例子来自 react 官网 。为了将 handleClick 函数中的 this 指向 Toogle 组件,我们需要给它手动绑定:this.handleClick = this.handleClick.bind(this)。
这时有的小伙伴会问:如果不绑定,它的 this 就不指向 Toogle 组件吗?
确实是这样,如果我们不对它进行绑定,this 打印出来将会是 undefined ,这点将在后面介绍。
可以看到,使用 bind 绑定可以实现我们的目的,但是可能有人不喜欢这种方法。由于函数的声明在 class 中,而绑定则在 constructor 中,一方面,这样会使 constructor 变得臃肿;另一方面,函数一旦多起来,我们就需要在声明之后再回到 constructor 中完成绑定,这样显得比较麻烦,并且容易遗漏。那有没有不需要在 constructor 中手动绑定的方法呢?答案是有的。
方式一:class fields 语法
class LoggingButton extends React.Component {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
// 注意: 这是 *实验性* 语法。
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
方式二:在回调中使用箭头函数
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
二、原因解析
有的小伙伴可能注意到了,在后面介绍的两种方式中,都使用到了箭头函数。而箭头函数的 this 是绑定词法作用域的,简单来说,箭头函数的 this 只跟它定义的地方有关,而普通函数的 this 更像是一个动态绑定的过程。由于箭头函数定义在组件中,它自然而然地就指向组件对象了。
那在定义在普通函数中的 this 默认指向什么呢?
答案是:window 对象。
很多小伙伴可能陷入了一个误区:我们将函数传给组件的 onClick ,调用它的不应该是组件对象吗,为什么会是 window 对象?
需要注意的是,我们只是将函数的引用传递给组件,但这并不意味着调用函数的就是组件对象。比如:
function A() {
this.print = function () {
console.log(this);
}
}
var a = new A();
a.print(); // 指向 A 的实例对象
var outerPrint = a.print;
outerPrint(); // 指向 window
由于普通函数的 this 指向更像是一个动态的问题,它取决于函数的调用位置。对于上面这段代码,我们称为 隐式丢失 ,不了解的小伙伴可以查一查 this 的四种绑定规则,这里不做过多介绍。
有的好奇宝宝又会问了:我明白了!这样的话,在之前的普通函数中,默认是指向 window 对象而非组件对象。但是为什么最后打印出来是 undefined 而不是 window 呢?
答案是:严格模式。
严格模式下,全局作用域函数中的 this 指向为 undefined。而 class 则是默认使用了严格模式。
类和模块的内部,默认就是严格模式,所以不需要使用
use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。
好耶!又明白一个知识点~
本文介绍了React中this的指向问题,特别是在事件处理函数中的使用。通过示例展示了如何通过构造函数中的bind方法、class fields语法以及使用箭头函数来确保this正确指向组件。还解释了普通函数中this的默认指向为window对象,但在严格模式下会变成undefined。文章总结了三种避免this丢失的方法,并强调了箭头函数在解决this绑定问题上的作用。
1202

被折叠的 条评论
为什么被折叠?



