[英]Nested “this” binding in ES6 classes using ReactJS
Reading through React docs I came across the following piece of code : 通过阅读React文档,我遇到了以下代码 :
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
My question is this: 我的问题是这样的:
In componentDidMount()
the arrow function () => this.tick()
"captures" the enclosing this
value and thus the proper tick
method is called on the <Clock>
component. 在
componentDidMount()
,箭头函数() => this.tick()
“捕获”包含this
值的值,因此在<Clock>
组件上调用了正确的tick
方法。
However tick
uses this
on its own to subsequently call the setState
method. 然而
tick
使用this
依靠自己的力量随后调用setState
方法。 How is this working without any bindings? 没有任何约束,这如何工作? In other words, how is
this.setState
working? 换句话说,
this.setState
如何工作?
Thanks 谢谢
According to the bind
function documentation , Function.prototype.bind
will create a new function with the same body and scope as the original function, but where this
in the scope of the new function refers to the argument that is passed into bind
. 根据该
bind
函数文档 , Function.prototype.bind
将创建一个相同的身体和范围作为原始功能的新功能,但是在this
新功能的范围指的是传入参数bind
。 This means you can pass a variable, lets say newContext
into the bind
function like: tick.bind(newContext)
, and every instance of this
inside of tick will be evaluated as newContext
. 这意味着你可以通过一个变量,可以说
newContext
到bind
的功能,如: tick.bind(newContext)
以及每一个实例this
蜱内将被评估为newContext
。 Although this
is a keyword referring to the context of the scope, we have changed the scope's context and so this
has a different value. 虽然
this
是指范围的上下文中的关键字,我们已经改变了范围的情况下,因此this
具有不同的值。
The arrow notation does something similar, and will replace the this
inside the value tick
with the value of the context of the arrow function's scope. 箭头符号的作用类似,它将用箭头函数作用域的上下文的值替换值
tick
的this
。 This is why the this
keyword inside of tick
does not have an undefined
value. 这就是为什么
tick
内部的this
关键字没有undefined
值的原因。
I think Rajesh has already explained it in the comments, still I will give it a try to explain. 我认为Rajesh已经在评论中对其进行了解释,但我仍将尝试进行解释。
An arrow function does not create its own this context, so this has its original meaning from the enclosing context ie from where it is being called which is componentDidMount
in your case. 箭头函数不会创建自己的上下文,因此它具有原始含义,即来自所包围的上下文,即从调用它的位置开始,在您的情况下为
componentDidMount
。
componentDidMount() {
// this refers to React.Component instance
this.timerID = setInterval(
() => this.tick(), // <----------------Same this is available here
1000
);
}
If you use bind you can achieve similar things via setting context via bind. 如果使用绑定,则可以通过设置绑定上下文来实现类似的目的。
componentDidMount() {
// this refers to React.Component instance from inside cdm method
this.timerID = setInterval(
this.tick.bind(this), // <----------------Same this is available here
// We have set it react component instance via bind
1000
);
}
Now after all those just look only at this method declaration - 现在,毕竟那些人只看这个方法声明-
tick() {
this.setState({
date: new Date()
});
}
Upto this point we can not say exactly what will be the value of this
inside tick
. 高达这点我们不能说什么将是值
this
里面tick
。 We also can not say that ' setState
' will be available on this
or not. 我们也不能说“
setState
”将可在this
与否。
Unless and until we see from where tick
will get called and what execution context will be attached to tick
at run time . 除非并且直到我们看到从哪里调用
tick
以及在运行时将附加哪些执行上下文附加到tick
。
Now if we see from where tick is getting called - componentDidMount
. 现在,如果我们从哪里看到滴答声被称为
componentDidMount
。 componentDidMount
is react component's life cycle method and it ( associated context ie this) definitely has setState
method available. componentDidMount
是反应组件的生命周期方法,并且它(关联的上下文,即此)肯定有setState
方法可用。
And in componentDidMount
we had set this
to react-component
context either via arrow function () => {}
or via bind
. 和在
componentDidMount
我们已经建立this
到react-component
经由箭头函数上下文或者() => {}
或经由bind
。 This is the reason because of which setState
is avaialble in tick
when called and you don't see any error. 这是因为调用该
setState
在tick
可用,而您看不到任何错误的原因。
But if you don't use arrow function or explicit bind you will be receiving following error on each time when setInterval
calls tick
function there by associating a global this with tick. 但是,如果不使用箭头函数或显式绑定 ,则每次
setInterval
通过将全局this与tick关联而在其中调用tick
函数时,都会收到以下错误。
"message": "Uncaught TypeError: this.setState is not a function",
See the below code snippet via running to see the error 通过运行查看下面的代码片段以查看错误
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { // now this inside tick will be pointing to setIntervals execution context which could be global this.timerID = setInterval( this.tick, 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.