真的对 javascript es6 箭头函数的“封闭范围”感到困惑

2023-11-24

  • 我在网上做了很多研究,阅读了很多帖子,包括MDN等等。
  • 据我所知,对于传统定义的函数,函数中的“this”是由调用/调用它们的对象定义的(以及几种不同的情况,对象文字,新的构造函数,事件处理程序等)。
  • 我知道对于箭头函数,“this”是按词法定义的,由enclosing context/scope,而不是通过对象调用它们(尽管我们可以使用传统定义的函数(例如 A)来包装箭头函数(例如 B),从而将对象引用首先传递给 A,然后传递给 B)

问题来了:

  1. 到底是什么enclosing context?这更加复杂,因为 ES6 允许{}成为一个块/范围/上下文。是{}作为足够好的分隔符来定义“封闭上下文”,或者它必须在函数范围内。

  2. 一个具体的例子:

     let EventEmitter = require('events').EventEmitter;
     class Person extends EventEmitter {
       constructor(name) {
         super();
         this.name = name;
       }
     }
     let mary = new Person('mary');
     mary.on('speak', (said) => {
       console.log(`${this.name}: ${said}`);
     });
     mary.emit('speak', 'you may delay, but time will not');
    

它只是设置一个自定义事件并在触发自定义事件时添加回调函数。为什么这里的箭头功能不起作用?

“mary”是调用“on”函数的对象,应将“on”中的“this”设置为“mary”。最重要的是,箭头函数是在其参数位置的“on”函数中定义的(从词法上来说足够了,对吧?),为什么箭头函数无法从其“封闭上下文”中获取“this”值,即,这里的“on”功能???

  1. 同样的例子,使用传统的函数定义:

     let EventEmitter = require('events').EventEmitter;
     class Person extends EventEmitter {
       constructor(name) {
         super();
         this.name = name;
       }
     }
     let mary = new Person('mary');
     mary.on('speak', function(s) {
       console.log(this);
     });
     mary.emit('speak', 'you may delay, but time will not');
    

现在可以了。据我了解,鉴于旧的函数定义方式,console.log(this) 现在可以动态绑定到调用它的对象。但是等等,“mary”是对象,“on”是被调用的立即函数。 “on”不应该为其中的匿名函数形成一个闭包吗?我记得嵌套函数中的“this”无法访问其闭包的“this”(封闭上下文,呵呵),因此不应获得“mary”引用。为什么它在这里起作用?

  1. 当我们在函数中谈论某件事(例如 A)时,是否意味着 A 必须位于{}函数的,或者 A 也可以在参数/参数区域中?那是,function(){A} vs. function(A){}.

  2. 类似地,如果箭头函数作为参数传递,例如function(()=>()) {},外部函数是否考虑了其封闭范围?或者在这种情况下,封闭范围将是外部函数的外部?

上面的话听起来可能非常愚蠢。非常感谢你的帮助。


我在这里可能没有准确地使用作用域这个词,但基本上只是将作用域视为变量名称到它们所引用的内存位置的映射;嵌套范围的名称/变量对shadow(覆盖)封闭(也称为父)范围内具有相同名称的关联。

function foo() { // this is the "enclosing scope" of bar
  var a = 4    <-----------+
                           |
  var b = a // refers to --+

  function bar() {
    var a = 7    <-----------+
                             |
    var c = a // refers to --+
  }
}

this行为方式完全相同a在上面的例子中就是这样做的。

function范围隐式定义了一个引用this但 ES2015 箭头函数作用域和块作用域没有。如果这些定义是明确的,它们将如下所示:

function foo() { // this is the enclosing scope of baz and the block below
  var this = ...  <-----------+--+
                              |  |
  var b = this // refers to --+  |
                                 |
  {                              |
    var q = this // refers to ---+
  }

  function bar() { // this is the enclosing scope of baz
    var this = ...  <-----------+--+
                                |  |
    var c = this // refers to --+  |
                                   |
    var baz = () => {              |
      var d = this // refers to ---+
    }
  }
}

实际上value在内存位置this指在特定范围内未按词汇定义;它在运行时设置为调用函数的对象(的内存位置)。但是一个引用对另一个引用的遮蔽总是按词法定义的。

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

真的对 javascript es6 箭头函数的“封闭范围”感到困惑 的相关文章

  • 为什么 `obj.foo = function() { };` 没有将名称 `foo` 分配给函数?

    从 ES2015 ES6 开始 函数有了专有名称 包括官方名称 name属性 而函数创建时的赋值除了明显的函数声明和命名函数表达式之外还有多种方式 比如给变量赋值 函数的名字设置为变量的名字 给对象属性赋值 函数的名称设置为属性的名称 甚至
  • 在 Meteor.method 中调用函数返回未定义

    过去几天我一直在尝试从 Meteor 方法获取返回对象 每次我这样做我都会得到undefined在客户端上 Meteor methods CORSTest function let url www theverge com 2017 4 1
  • 如何制作像Stackoverflow一样的可折叠评论框

    我正在构建一个网站 并且有一个状态更新列表 我希望允许用户为列表中的每个项目撰写评论 但是我正在尝试实现一个类似于堆栈溢出工作方式的用户界面 特别是可折叠的评论表单 列表 用户在其中单击对列表中的特定状态更新添加评论 并且在列表中的该项目下
  • ExtJS 4:克隆商店

    我正在尝试找出如何克隆Ext data Store不保留旧的参考 让我用一些代码更好地解释一下 这是源商店 var source Ext create Ext data Store fields name age data name foo
  • 通过 HTML5 文件和 URL API 正确创建和提供 PDF Blob

    好吧 假设我有文档数据存储在某处 让我们任意取this pdf http www grida no climate ipcc tar wg1 pdf tar 01 pdf 问题 1 我想要做的是对此 URL 进行 AJAX 调用 因为我需要
  • 如何在 JavaScript 中构建一个计算数组中出现次数的对象?

    我想计算数组中某个数字出现的频率 例如 在Python中我可以使用Collections Counter创建一个字典 记录某个项目在列表中出现的频率 据我所知 JavaScript 是这样的 var array 1 4 4 5 5 7 va
  • 为什么我的 onclick 事件自动触发

    加载页面时最初显示 Hello World 我希望它仅在单击按钮后显示 我知道我可以通过向按钮添加内联事件侦听器来做到这一点 我可以只用脚本编写所有这些代码吗
  • JointJS - 处理链接删除点击

    创建链接后 将鼠标悬停在其上会显示红色 X 以将其删除 单击此按钮将触发一系列事件 通过订阅 全部 活动收集 单元格 向下指针 链接 向下指针 cell pointermove x5 似乎可疑 单元格 指针向上 在浏览了文档并花费了太长时间
  • t /= d 是什么意思? Python 和错误

    t current time b begInnIng value c change In value d duration def easeOutQuad swing function x t b c d alert jQuery easi
  • Web浏览器控件:如何捕获文档事件?

    我正在使用 WPF 的 WebBrowser 控件加载一个简单的网页 在这个页面上我有一个锚点或一个按钮 我想在我的应用程序后面的代码中 即在 C 中 捕获该按钮的单击事件 WebBrowser 控件是否有办法捕获加载页面元素上的单击事件
  • 比较 javascript 元素和 scala 变量的 Play 框架 Twirl 模板

    如下面的代码示例所示 我想比较 scala 辅助元素内的 javascript 元素 然而 即使存在元素 abcde 它也始终返回 false 除了使用标签之外 如何获取 scala 辅助元素内的 javascript 值 appSeq S
  • 在外部单击时关闭弹出 div

    我有一个弹出 div 仅在单击特定按钮时显示 单击同一按钮时它甚至会隐藏 我的问题是 我还想在单击外部任何地方时隐藏 div 我无法这样做 因为弹出 div 位于主包装类内部 并且无法通过在包装类上使用 click 事件并使其隐藏来做到这一
  • 如何在 OpenLayers 3 中删除监听器

    我做了一个copy https gis stackexchange com questions 178222 how to delete a listener in openlayers 3我在 stackoverflow 上提出的问题 因
  • IE6 丢失查询字符串

    我有一个使用 javascript 从查询字符串中获取值的页面window location 从网络服务器运行时效果很好 但如果我通过将其放在地址栏中使用 IE6 在本地运行它 c mysite index htm 网站创建的任何查询字符串
  • 如何使用 .append() 将 React 组件附加到 HTML 元素

    我正在尝试对我的博客实现无限滚动 我有 const articlesHTML document querySelector articles 作为容器 每次点击装载更多按钮 我想将新文章附加到主 html 元素 如下所示 const res
  • Jade(当前称为“Pug”)模板引擎中的循环

    我想使用一个简单的循环 例如for int i 0 i lt 10 i 如何在 Jade 引擎中使用它 我正在使用 Node js 并使用expressjs 框架 例如 for var i 0 i lt 10 i li array i 你可
  • 使用 JavaScript 从 URL 变量读取来加载不同的 CSS 样式表

    我试图在我的 WordPress 博客上使用两个不同的样式表 以便在通过 Web 访问页面时使用一个样式表 而在通过我们的 iOS 应用程序访问博客内容时使用另一个样式表 现在 我们将 app true 附加到来自 iOS 应用程序的 UR
  • 为什么我无法通过 lambda 捕获“this”指针?

    考虑以下代码 class A public void foo auto functor this A a this auto functor a The compiler won t accept this instead of a a g
  • 使用 stopPropagation() 处理 React 事件委托

    我有一个 React 项目 应该可以放置在任何网站上 我的想法是 我托管一个 javascript 文件 人们放置一个具有特定 ID 的 div 然后 React 在该 div 中进行渲染 到目前为止 除了点击事件之外 这是有效的 这些事件
  • Angular 5 中 Observable.ForkJoin 的重复 Http 请求

    我有一个 Angular 5 应用程序 组件中包含以下代码 ngOnInit Observable forkJoin this highlightedInsight this insightService getHighlightedIns

随机推荐