我知道this
绑定的一般理论(函数调用站点重要,隐式,显式绑定等等)以及在React中解决此绑定问题的方法,所以它始终指向我想要this
是什么(在构造函数中绑定,箭头函数等),但我正在努力获得内部机制。
看看这两段代码:
class demo extends React.component {
goToStore(event) {
console.log(this)
}
render() {
<button onClick={(e) => this.goToStore(e)}>test</button>
}
}
VS
class demo extends React.component {
goToStore(event) {
console.log(this)
}
render() {
<button onClick={this.goToStore}>test</button>
}
}
我所知道的是:
this
方法中的render()
自动绑定(通过React)到组件实例this
解析为undefined
据我所知,在第一版的理论中,会发生以下情况:
this
时,它都会从环境中获取this
(在本例中来自{ {1}})render()
方法,这是一个常规函数。goToStore
)object.function()
将是上下文对象,在此类函数调用中它将用作object
this
方法中,词法拾取(用作上下文对象)将正确解析为组件实例我觉得3.和4.不是这里的情况,因为那样它将适用于2.案例:
goToStore
还有<button onClick={this.goToStore}>test</button>
上下文对象。
在这个特殊情况下,一步一步地发生了什么?
答案 0 :(得分:4)
正如MDN文档陈述
箭头功能没有自己的功能;这个值 使用封闭执行上下文
所以你会想到
A extends any
是一个匿名函数,可以写成
onClick={(e) => this.goToStore(e)}
现在这里的匿名函数 (e) => {
return this.goToStore(e)
}
引用了render函数的词汇上下文,而后者又引用了React Class实例。
现在
上下文通常取决于如何调用函数。当一个函数作为一个对象的方法被调用时,它被设置为调用该方法的对象:
this
当使用new运算符调用函数来创建对象的实例时,同样的原则也适用。以这种方式调用时,函数范围内的this值将设置为新创建的实例:
var obj = {
foo: function() {
return this;
}
};
obj.foo() === obj; // true
当作为未绑定函数调用时,它将默认为浏览器中的全局上下文或窗口对象。
所以这里因为函数被称为function foo() {
alert(this);
}
foo() // window
new foo() // foo
,所以它里面会引用React组件的上下文。
但是当您编写this.goToStore()
时,该函数不会被执行,但是它的引用被分配给onClick函数,该函数随后会调用它,导致onClick={this.goToStore}
在函数内部未定义为函数在this
对象的上下文中运行。
现在即使window
有效,每当调用render时,都会创建一个新的函数实例。在你的情况下,它很容易避免,只需使用箭头函数语法创建函数goToStore。
onClick={(e) => this.goToStore(e)}
查看文档以获取有关this
答案 1 :(得分:1)
在案例1中,正如您所说,上下文是从环境中获取的。 对于案例2,您必须记住ES6中的类语法只是JavaScript依赖于实现OOP的更麻烦的原型语法的语法糖。
基本上,在第二个例子中,你所做的就是这样:
function demo() {
// this is the constructor
}
demo.prototype.goToStore = function() {
// handler
};
demo.prototype.render = function() {
return React.createElement('button', onClick: this.goToStore);
}
如您所见,onClick
属性只是接收对该函数的引用。每当调用该函数时,都不会绑定this
,并且它将在window
对象的上下文中运行。
在较旧的图书馆中,在现代编译器出现之前,我们曾经在这里做过类似的事情:
function demo() {
// this is the constructor
this.goToStore = this.goToStore.bind(this);
// same for every other handler
}
demo.prototype.goToStore = function() {
// handling code.
};
demo.prototype.render = function() {
// this goToStore reference has the proper this binded.
return React.createElement('button', onClick: this.goToStore);
}
如今,我提出的最后一个例子是由所有现代转录器自动处理的。当您在任何类中使用胖箭头方法语法时,Babel基本上在构造函数中执行自动绑定:
class demo extends Anything {
constructor() {
}
bindedMethod = () => {
// my context will always be the instance!
}
}
由于存在细微差别,所有转换器都会将bindedMethod
的定义移动到构造函数,其中this
将绑定到运行构造函数的当前实例。
答案 2 :(得分:0)
执行渲染代码时,this
引用组件类,因此它能够引用正确的函数。这意味着element.onClick
指向goToStore
方法。
当在浏览器中调用该函数时,它将从html元素的上下文(即element.onClick()
)调用。因此,除非goToStore
方法绑定到组件类的上下文,否则它将从元素的上下文继承this
。
This answer提供了一些更相关的信息和进一步阅读。