我知道 this
绑定(bind)的一般理论(函数调用点很重要,隐式绑定(bind),显式绑定(bind)等...)以及解决 React 中 this 绑定(bind)问题的方法,所以它总是指向我想要的 this
是什么(在构造函数中绑定(bind)、箭头函数等),但我正在努力获得内部机制。
看看这两段代码:
class demo extends React.component {
goToStore(event) {
console.log(this)
}
render() {
<button onClick={(e) => this.goToStore(e)}>test</button>
}
}
对比
class demo extends React.component {
goToStore(event) {
console.log(this)
}
render() {
<button onClick={this.goToStore}>test</button>
}
}
我知道的是:
- 在两个版本中,我们最终都在 goToStore 方法中成功,因为
render()
方法中的this
自动绑定(bind)(通过 React)到组件实例 - 第一个因此成功,
- 第二个失败,因为es6中的类方法没有绑定(bind)组件实例,从而将方法中的
this
解析为undefined
据我所知,理论上在第一个版本中会发生以下情况:
- 按钮点击处理程序是一个匿名的arrow 函数,因此每当我在其中引用
this
时,它都会从环境中获取this
(在本例中来自render()
) - 然后调用
goToStore
方法,这是一个常规函数。 - 因为调用似乎符合隐式绑定(bind)规则 (
object.function()
)object
将是上下文对象,在此类函数调用中将使用它作为这个
- 因此,在
goToStore
方法中,词法选取的 this(用作上下文对象)将正确解析为组件实例
我觉得 3. 和 4. 在这里不是这种情况,因为它适用于 2. 情况:
<button onClick={this.goToStore}>test</button>
还有 this
上下文对象。
在这种特殊情况下究竟发生了什么,一步一步?
最佳答案
正如 MDN 文档所述
An arrow function does not have its own this; the this value of the enclosing execution context is used
所以你会想到
onClick={(e) => this.goToStore(e)}
作为一个匿名函数可以写成
(e) => {
return this.goToStore(e)
}
现在在这个匿名函数中 this
指的是渲染函数的词法上下文,它又指的是 React 类实例。
现在
上下文 通常由函数的调用方式决定。当函数作为对象的方法被调用时,this 被设置为调用该方法的对象:
var obj = {
foo: function() {
return this;
}
};
obj.foo() === obj; // true
当使用 new 运算符调用函数来创建对象实例时,同样的原则也适用。当以这种方式调用时,函数范围内的 this 的值将被设置为新创建的实例:
function foo() {
alert(this);
}
foo() // window
new foo() // foo
当作为未绑定(bind)函数调用时,这将默认为浏览器中的全局上下文或窗口对象。
所以在这里,由于函数的调用方式类似于 this.goToStore()
,this 内部将引用 React 组件的上下文。
然而,当您编写 onClick={this.goToStore}
时,该函数并未执行,而是将其引用分配给 onClick 函数,稍后调用它,导致 this
在函数内部未定义,因为函数在 window
对象的上下文中运行。
现在即使 onClick={(e) => this.goToStore(e)}
有效,每当调用 render 时都会创建一个新的函数实例。在您的情况下,很容易避免,只需使用箭头函数语法创建函数 goToStore。
goToStore = (e) => {
}
查看文档以获取有关 this
的更多详细信息
关于javascript - 带有箭头函数的事件处理程序如何实现上下文绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47679673/