真的很困惑"封闭范围" javascript es6箭头功能

时间:2017-03-17 01:30:34

标签: javascript ecmascript-6 this arrow-functions

  • 我在网上做了很多研究,阅读了很多帖子,包括MDN等等。
  • 我理解对于传统定义的功能,"这个"函数内部由调用/调用它们的对象定义(以及几种不同的情况,对象文字,新构造函数,事件处理程序等)。
  • 我理解箭头功能,"这个"在词汇上,由封闭的上下文/范围定义,而不是由调用它们的对象定义(尽管我们可以使用传统定义的函数(比方说,A)来包装箭头函数(比方说,B),从而将对象引用传递给A,并且然后到B)

以下是问题:

  1. 究竟什么是封闭的背景?这是进一步复杂的,因为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');

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

    "玛丽"是调用" on"的对象。功能,应该设置"这个"在" on"玛丽"。最重要的是,箭头功能在" on"中定义。函数在其参数位置(在词法上足够,对吗?),为什么箭头函数不能得到"这个"来自"封闭上下文"的价值,即" on"功能在这里???

    1. 使用传统函数定义的相同示例:

      ${this.name}: ${said}

    2. 现在它有效。我理解,鉴于旧的函数定义方式,console.log(this)现在可以动态绑定到调用它的对象。但等等," mary"是对象和" on"是被调用的直接函数。不应该" on"为其中的匿名函数形成一个闭包?我记得"这个"在嵌套函数内无法访问"这个"它的封闭(封闭的背景,再次,呵呵),因此不应该得到" mary" refernce。为什么它在这里有用?

      1. 当我们在函数中讨论某事(比如说A)时,它是否意味着A必须在函数的{}中,或者A也可以在参数/参数区域中?也就是说,function(){A} vs. function(A){}。

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

      3. 以上可能听起来很愚蠢。非常感谢你的帮助。

4 个答案:

答案 0 :(得分:2)

我可能不会在这里精确地使用“范围”一词,但基本上只是将范围视为变量名称的映射,以及它们所指向的内存中的位置;嵌套范围的名称/变量对阴影(覆盖)在封闭(又称父级)范围内具有相同名称的关联。

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 lambda范围和块范围不。如果它们是明确的,那么这些定义会是什么样的:

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

this在特定范围内引用的内存位置的实际不是词法定义的;它在运行时设置为调用函数的对象的(内存位置)。但是,另一个引用的阴影总是在词法上定义。

答案 1 :(得分:0)

this箭头函数是最近的函数范围,意味着使用 function 关键字定义的函数范围发生。

即使箭头函数以某种方式嵌套,这也适用,如

function scope() {
    const arrow = a => b => this.foo(a, b);
}

此处有问题的thisthis的{​​{1}}。

  

&#34;玛丽&#34;是调用&#34; on&#34;的对象。功能,应该设置&#34;这个&#34;在&#34; on&#34;玛丽&#34;。最重要的是,箭头功能在&#34; on&#34;中定义。函数在其参数位置(在词法上足够,对吗?),为什么箭头函数不能得到&#34;这个&#34;来自&#34;封闭上下文&#34;的价值,即&#34; on&#34;功能在这里???

是的,scope中的thison。但是,这并不意味着mary的实施将其on的回调调用为mary,或任何其他特定的this - 由this的实施。此外,&#34; context&#34;箭头函数控制它的&#39;这个&#39;不是on,也不是整个on语句,也不是一些封闭的mary.on块,而是功能范围在其中发生。

答案 2 :(得分:0)

我很难解密这个概念,但是最近我全神贯注于它。

因此,要理解这一点,我们应该先了解什么是 scope ?范围是引擎在查找变量时使用的一组规则。因此,在实践中,You don't know JS书中将其描述为引擎与作用域之间的对话非常好。如果您考虑一个简单的左手任务,例如let a = 1;,则对话将类似于:

  • 引擎:嘿,范围,有什么叫“ a”吗?
  • 范围:否
  • 引擎:很酷,请您记住从现在开始有一个成员“ a”,帮我一个忙,请给它赋值“ 1”';
  • 范围:编译器

现在想象一个场景:console.log(a)

  • Engine:嘿,我曾经听说过控制台
  • 范围:为什么我有,它是一个对象
  • 引擎:很酷,但您是否也听说过它的属性日志
  • 范围:是的,是的,我做了
  • Engine:非常感谢范围,我看到它是一个函数。我还有一个问题,你知道这个叫“ a”的成员吗?它的价值如何?
  • 范围:我也知道,它的值是1
  • 引擎:范围不错,我已经准备好了。现在正在调用日志,而我正在通过

在JavaScript中,有多种定义范围的方法。但是,为了简单起见,我们仅讨论函数范围。 (您也可以通过块来定义范围)

// global scope
function foo(a) {
    //foo scope
    var b = a * 2;

    function bar(c) {
        // bar scope
        console.log( a, b, c );
    }

    bar(b * 3);
}

foo( 2 ); // 2 4 12

在上面的示例中,我认为很容易发现两个范围,foo范围和bar范围。

如您所见,bar在foo中被调用,并显示ab范围内的3个值fooc bar中的。之所以能够这样做,是因为范围查找不仅仅发生在当前范围内,它会继续检出其父范围(封闭范围),直到达到全局范围为止。

所以在层次结构中,我们会看到类似的东西

  • 全球范围
  • -> foo作用域
  • ||->条形范围

在这种情况下,foo范围是bar的包围范围,因为它实际上将bar括在其中。

答案 3 :(得分:-1)

传递给事件发射器回调的函数不会绑定到发射器的作用域,除非你这样做,无论它是传统函数还是胖箭头函数。

当他们说胖箭头函数绑定到词法范围时,他们意味着它不会创建自己的新范围。

考虑:

address