当前位置: 首页 > 面试题库 >

具有箭头功能的事件处理程序如何实现上下文绑定

袁旻
2023-03-14
问题内容

我了解this绑定的一般理论(重要的函数调用站点,隐式,显式绑定等)以及解决React中此绑定问题的方法,因此它始终指向我想要的对象this(在构造函数,箭头函数等),但我正在努力获取内部机制。

看一下这两段代码

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方法成功,因为方法this内部render()自动(由React绑定)到组件实例
  • 因此,第一个成功了,
  • 第二个失败,因为es6中的类方法未绑定到组件实例,因此this将方法解析为undefined

据我了解,从理论上讲,在第一版中会发生以下情况:

  1. 按钮点击处理程序是一个匿名 箭头 函数,因此,每当我在其中引用this时,它都会this从环境中拾取(本例中为render()
  2. 然后调用goToStore方法,即常规函数。
  3. 因为该调用似乎符合隐式绑定(object.function())的规则,所以object它将成为上下文对象,并且在此类函数调用中,它将用作this
  4. 因此,在goToStore方法内部,按词法拾取该对象(用作上下文对象)将正确解析为组件实例

我觉得这里不是3.和4.,因为那样就适用于2.情况:

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

还带有this上下文对象。

在这种特定情况下,逐步发生了什么?


问题答案:

如MDN文档所述

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

所以你会想到

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

作为匿名函数,可以写成

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

现在,这里的匿名函数this是指render函数的词法上下文,而后者又是React类实例。

现在

上下文 通常由函数的调用方式决定。当将函数作为对象的方法调用时,会将其设置为调用该方法的对象:

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

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

使用new运算符调用函数以创建对象的实例时,适用相同的原理。以这种方式调用时,在函数范围内的this值将设置为新创建的实例:

function foo() {
    alert(this);
}

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

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

因此,由于在函数this.goToStore() 内部这样调用函数,因此它将引用React组件的上下文。

但是,当您编写时onClick={this.goToStore},不会执行该函数,而是将其引用分配给onClick函数,该函数随后会调用它,导致this该函数在函数内部在window对象的上下文上运行时未定义

现在即使onClick={(e) => this.goToStore(e)}可以使用,只要调用render就会创建一个新的函数实例。在您的情况下,只需使用箭头函数语法创建函数goToStore即可避免这种情况。

goToStore = (e) => {

}

检查文档以获取更多详细信息 this



 类似资料:
  • 本文向大家介绍Asp.net实现MVC处理文件的上传下载功能实例教程,包括了Asp.net实现MVC处理文件的上传下载功能实例教程的使用技巧和注意事项,需要的朋友参考一下 上传于下载功能是程序设计中非常常见的一个功能,在ASP.NET程序开发中有着非常广泛的应用。本文就以实例形式来实现这一功能。 一、概述 如果你仅仅只有Asp.net Web Forms背景转而学习Asp.net MVC的,我想你

  • 本文向大家介绍Asp.net利用一般处理程序实现文件下载功能,包括了Asp.net利用一般处理程序实现文件下载功能的使用技巧和注意事项,需要的朋友参考一下 首先有一个html页面,页面有一个链接,点击链接弹出文件下载/保存(类似迅雷下载链接) 一般处理程序的代码如下 点击第一个链接访问,显示如下: 点击第二个链接访问,下载文件: 由于我之前已经测试过一次,所以这次下载时命名为readme(1).t

  • 本文向大家介绍Servlet实现代理文件下载功能,包括了Servlet实现代理文件下载功能的使用技巧和注意事项,需要的朋友参考一下 用户向代理服务器发送请求,代理服务器从后端服务器上获取文件,并返回给用户 web.xml: servlet: 参考:一个文件下载的Servlet 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 请先按(按住)箭头键,然后按非箭头键,测试以下代码。至少在Mac中,你会看到箭头键不断地应用它们的功能,而其他键则没有。有没有人知道如何使其他键在处理过程中连续应用(即不通过改变OSX的功能)?

  • 我在开发一个消息路由器的过程中,我来到了处理意外的点,并把一些错误处理到位。 在我的代码中,我能够区分何时由于错误消息而发生异常,这是我唯一想将消息发送到死信终端的情况。在所有其他情况下,我认为异常是由架构体系问题引起的(例如数据库/JMS终端变得不可用),在这种情况下,我希望消息回滚到路由开始。 查看驼峰文档,唯一一个支持死信的错误处理程序是,但问题是这个错误处理程序没有被处理。 那么,有没有一

  • 问题内容: 我们应该避免在render内部绑定方法,因为在重新渲染期间它将创建新方法而不是使用旧方法,这会影响性能。 所以对于这样的场景: 我们可以在构造函数中绑定方法: 或者我们可以使用属性初始化器语法: 现在让我们考虑一下要传递一些额外参数的情况,在一个简单的todo应用中说,项目的onclick我需要从数组中删除该项目,为此我需要在每个项目中传递项目索引或todo名称onClick方法: 现