带箭头函数的事件处理程序如何实现上下文绑定 [英] How does event handlers with arrow functions achieve context binding

查看:373
本文介绍了带箭头函数的事件处理程序如何实现上下文绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个绑定的一般理论(函数调用站点重要,隐式,显式绑定等等)和解决问题的方法React中的这个绑定所以它总是指向我想要的这个(在构造函数,箭头函数等中绑定),但我正在努力获得内部机制。 / p>

看看这两段代码:

  class demo扩展React.component {
goToStore(event){
console.log(this)
}

render(){
< button onClick = {(e)=> this.goToStore(E)}>试验< /按钮>
}
}

vs。

 类演示扩展React.component {
goToStore(event){
console.log(this)
}

render(){
< button onClick = {this.goToStore}> test< / button>
}
}

我所知道的是:




  • 在两个版本中我们在goToStore方法中成功结束,因为这个在<$ c里面$ c> render()方法自动绑定(通过React)到组件实例

  • 第一个成功因为,

  • 第二个失败,因为es6中的类方法没有绑定到组件实例,因此在方法中解析这个未定义



据我所知,在第一版的理论中,会发生以下情况:


  1. 按钮点击处理程序是一个匿名箭头功能,所以每当我引用这个在其内部,它从环境中获取(在本例中来自 render()

  2. 然后它调用 goToStore 方法,这是一个常规函数。

  3. 因为调用似乎符合隐式绑定的规则( object.function() object 将是上下文对象和在这样的函数调用中,它将被用作这个

  4. 所以,在 goToStore lexically拾取的方法(用作上下文对象)将正确解析为组件实例

我感觉3.并且4.这不是这种情况,因为它适用于2.案例:

 < button onClick = {this .goToStore}>试验< /按钮> 

还有这个上下文对象。



在这个特殊情况下,一步一步发生了什么?

解决方案

由于MDN文档状态


箭头函数没有自己的这个;使用
封闭执行上下文的这个值


所以你会想到

  onClick = {(e)=> this.goToStore(e)} 

是一个匿名函数,可以写成

 (e)=> {
返回this.goToStore(e)
}

现在在这里匿名函数这个引用渲染函数的词汇上下文,后者又引用React类实例。



现在



上下文通常取决于如何调用函数。当一个函数作为一个对象的方法被调用时,它被设置为调用该方法的对象:

  var obj = {
foo:function(){
返回此;
}
};

obj.foo()=== obj; // true

当使用new运算符调用函数来创建一个实例时,同样的原则适用宾语。以这种方式调用时,函数范围内的this值将设置为新创建的实例:

  function foo(){
alert(this);
}

foo()//窗口
新foo()// foo

当作为未绑定函数调用时,这将默认为浏览器中的全局上下文或窗口对象。



所以这里函数被称为 this.goToStore()这里面会引用React组件的上下文。



但是当你写 onClick = {this.goToStore} ,该函数没有被执行但是它的引用被分配给onClick函数,然后它会调用它,导致这个在函数内部未定义,因为该函数在窗口对象的上下文中运行。



现在即使 onClick = {(e)=> this.goToStore(e)} 工作,只要调用render,就会创建一个新的函数实例。在你的情况下,它很容易避免,只需使用箭头函数语法创建函数goToStore。

  goToStore =(e)=> ; {

}

检查文档以获取有关 this


I know about the general theory of this binding (function call site what matters, implicit, explicit binding, etc...) and the methods to solving the problem of this binding in React so it always points to what I want this to be (binding in constructor, arrow functions, etc), but I am struggling to get the inner mechanisms.

Take a look at these two pieces of code:

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>
  }
}

What I know is that:

  • in both versions we end up successfully in the goToStore method, because the this inside the render() method is automatically bound (by React) to the component instance
  • the first one succeeds because of that,
  • the second one fails, because class methods in es6 are not bound to the component instance, thus resolving this in the method to undefined

In theory in the first version as far as I understand, the following occurs:

  1. the button click handler is an anonymous arrow function, so whenever I reference this inside of it, it picks up this from the environment (in this case from render())
  2. then it calls the goToStore method, that is a regular function.
  3. because the call seems to fit the rules of implicit binding (object.function()) object will be the context object and in such function calls it will be used as this
  4. so, inside the goToStore method the lexically picked up this (used as a context object) will resolve to the component instance correctly

I feel 3. and 4. is not the case here, because then it would apply to the 2. case:

<button onClick={this.goToStore}>test</button>

Also with this the context object.

What is happening exactly in this particular case, step-by-step?

解决方案

As the MDN docs states

An arrow function does not have its own this; the this value of the enclosing execution context is used

So you would think of

onClick={(e) => this.goToStore(e)}

as being an anonymous function which can be written as

    (e) => { 
         return this.goToStore(e) 
    }

Now here in this anonymous function this refers to the lexical context of the render function which in turn refers to the React Class instance.

Now

Context is most often determined by how a function is invoked. When a function is called as a method of an object, this is set to the object the method is called on:

var obj = {
    foo: function() {
        return this;   
    }
};

obj.foo() === obj; // true

The same principle applies when invoking a function with the new operator to create an instance of an object. When invoked in this manner, the value of this within the scope of the function will be set to the newly created instance:

function foo() {
    alert(this);
}

foo() // window
new foo() // foo

When called as an unbound function, this will default to the global context or window object in the browser.

So here since the function is called like this.goToStore() this inside it will refer to the context of React component.

However when you write onClick={this.goToStore}, the function is not executed but a reference of it is assigned to the onClick function, which then later invokes it, causing this to be undefined inside the function as the function runs on the context of the window object.

Now even though onClick={(e) => this.goToStore(e)} works, whenever render is called a new function instance is created. In your case its easy to avoid, just by created the function goToStore using arrow function syntax.

goToStore = (e) => {

}

Check the docs for more details on this

这篇关于带箭头函数的事件处理程序如何实现上下文绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆