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

2024-01-16

我了解一般理论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>
  }
}

我所知道的是:

  • 在这两个版本中,我们都在 goToStore 方法中成功结束,因为this在 - 的里面render()方法自动绑定(通过 React)到组件实例
  • 第一个成功因此,
  • 第二个失败,因为es6中的类方法没有绑定到组件实例,因此解决了this在方法中undefined

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

  1. 按钮点击处理程序是匿名的arrow函数,所以每当我引用this在它里面,它拾起this来自环境(在本例中来自render())
  2. 然后它调用goToStore方法,这是一个常规函数。
  3. 因为调用似乎符合隐式绑定的规则(object.function()) object将是上下文对象,在此类函数调用中它将用作this
  4. 所以,在里面goToStore词法上拾取的 this(用作上下文对象)的方法将正确解析为组件实例

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

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

还带有this上下文对象。

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


正如 MDN 文档所述

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

所以你会想到

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

作为一个匿名函数,可以写成

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

现在在这个匿名函数中this指的是渲染函数的词法上下文,而渲染函数又指的是 React 类实例。

Now

Context通常由函数的调用方式决定。当函数作为对象的方法被调用时,this 被设置为调用该方法的对象:

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

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

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

function foo() {
    alert(this);
}

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

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

所以这里因为该函数被称为this.goToStore()其中的 this 将引用 React 组件的上下文。

然而当你写onClick={this.goToStore},该函数没有执行,但它的引用被分配给 onClick 函数,然后该函数稍后调用它,导致this当函数在函数的上下文中运行时,函数内部未定义window object.

现在尽管onClick={(e) => this.goToStore(e)}每当调用 render 时都会创建一个新的函数实例。在您的情况下,很容易避免,只需使用箭头函数语法创建函数 goToStore 即可。

goToStore = (e) => {

}

检查文档以获取更多详细信息this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有箭头函数的事件处理程序如何实现上下文绑定 的相关文章

  • WebPack 源映射令人困惑(重复文件)

    我决定在我今天正在启动的一个新项目上尝试 WebPack 并且我从源映射中得到了非常奇怪的行为 我在文档中找不到任何相关信息 在浏览 StackOverflow 时也找不到其他人遇到此问题 我目前正在查看由以下公司制作的 HelloWorl
  • Heroku 上重启后 Better-SQLite3 数据库重置

    我有一个 Discord 机器人better sqlite3 https github com JoshuaWise better sqlite3硬币和 XP 数据库 直到两周前它一直工作得很好 现在 每次重新启动后 它只会恢复 XP 和硬
  • 从 Eclipse 导出后,WAR 文件中缺少一些必要的库 - 为什么?

    我接手了一个大学的项目 其中包含一些 Web 服务 通过将项目导出为 WAR 文件 一些库包含在文件中 例如 Axis2 而另一些则不包含 hibernate JDBC 驱动程序 另外 添加到类路径中的 jar 尚未导出 所有库都位于硬盘驱
  • AngularJS 和 Apiary.IO - 无法读取任何响应标头?

    我使用 Apiary io 模拟我的 API 但不知怎的 我无法使用 angularJS 从响应对象中读取任何标头 我确信我至少通过检查 firebug 正确设置了 Content Type application json Angular
  • 在 Node.js 中实现服务器发送事件的简单方法?

    我环顾四周 似乎在 Node js 中实现 SSE 的所有方法都是通过更复杂的代码 但似乎应该有一种更简单的方法来发送和接收 SSE 是否有任何 API 或模块可以让这件事变得更简单 这是一个每秒发送一个服务器发送事件 SSE 的 Expr
  • 传单圆圈绘制/编辑问题

    我第一次制作传单 并面临绘制圆圈和编辑 更改圆圈位置 的问题 我面临的问题是 编辑 移动 圆从一个位置到另一位置会改变其半径 Note 请尝试在给定的小提琴中在地图顶部创建圆圈 然后通过单击编辑按钮将其移动到底部 如果我在地图的顶部创建圆圈
  • 如何在 .js 中的字符串中插入来自 ruby​​ 示例的变量[重复]

    这个问题在这里已经有答案了 在 ruby 中 您可以将变量插入到字符串中 如下所示 x sake puts I like x I like sake 例如 def what i like word I like word end 在 jav
  • Express.js - 监听关闭

    我有一个使用 Express 的 Node js 应用程序 在该应用程序中 我有一个如下所示的块 const app require app const port process env PORT 8080 const server app
  • 如何使用 Selenium webdriver 测试对 SVG 对象的点击?

    我正在尝试编写代码来检查单击 SVG 对象的功能 例如此 URL 上的美国州 http www amcharts com svg maps map usa 这可行 但是有更好的方法吗 不需要物理移动鼠标的东西 robert new Robo
  • 如何在React中处理多个路由器

    假设我们有一个网络应用程序 它通常有很多视图 例如索引页面 管理面板 帮助页面 联系人等 我在主index js 中使用react router dom 来处理它们 它工作得很好 但是现在我在开发管理面板时遇到了问题 它是 index js
  • 可点击的进度条

    我正在使用 Angular 并在 JavaScript 的帮助下开发了一个可点击的进度条 这是我能做到的最好的 有没有办法将滑块放置在进度条内但不干扰进度可视化 堆栈闪电战 https stackblitz com edit angular
  • 字符串化 JavaScript 对象

    我正在寻找字符串化一个对象 我想要这样的输出 1 valeur dalebrun usager experttasp date 2013 08 20 16 41 50 2 valeur test usager experttasp date
  • Nuxt + Vuex - 如何将 Vuex 模块分解为单独的文件?

    在 Nuxt 文档中 here https nuxtjs org guide vuex store module files 它说 您可以选择将模块文件分解为单独的文件 state js actions js mutations js an
  • 访问事件处理程序内的对象实例

    我有以下代码 var myObj inputs document getElementsByTagName input attachKeyEvent function for var i 0 i lt this inputs length
  • 使用 sockjs 和 stomp 进行 /info 请求期间没有 cookie

    我正在尝试将 Spring Security 与 websockets 一起使用 作为一个例子 我正在使用 spring websocket chat https github com salmar spring websocket cha
  • 使用 Lodash 循环 JavaScript 对象中的属性

    是否可以循环访问 JavaScript 对象中的属性 例如 我有一个 JavaScript 对象定义如下 myObject options property1 value 1 property2 value 2 属性将动态添加到该对象 有没
  • 谷歌浏览器不显示一个网站的alert()弹出窗口

    我正在开发一个 javascript 循环 该循环会随着循环的进行而提醒每个键值 为了加快速度 我选中了 阻止此页面创建其他对话框 框 通常这只会抑制一个例程的弹出窗口 但它们还没有回来 在 Google Chrome 中 alert 消息
  • 如何在javascript中删除对象的一部分

    这是我的代码 var data btn click function total data push id total cell val1 val2 val3 每次用户点击btn按钮 我向数据对象添加一些值 现在我的问题是如何删除有的部分i
  • Recoil 中的动态原子键

    我正在尝试创建一个动态表单 其中表单输入字段是根据 API 返回的数据呈现的 由于atom需要有一个唯一的键 我尝试将它包装在一个函数中 但是每次我更新字段值或重新安装组件 尝试更改选项卡 时 我都会收到一条警告 我在这里做了一个小的运行示
  • 如何连接/组合两个数组以连接成一个数组?

    我正在尝试将 JavaScript 中的 2 个数组合并为一个 var lines new Array a b c lines new Array d e f 这是一个简单的例子 我希望能够将它们组合起来 这样当读取第二行时 数组中的第四个

随机推荐