【问题标题】:How exactly does a Closure remember its lexical scope?闭包究竟是如何记住它的词法范围的?
【发布时间】:2017-10-16 07:13:26
【问题描述】:

所以我明白 JavaScript 中的闭包是做什么的,但我不明白它“如何”记住的。

使用 YDKJS 书中的例子:

function foo() {
    var a = 2;

    function bar() {
        console.log( a );
    }

    return bar;
}

var baz = foo();

baz()//Prints 2

我知道bar 正在返回,并且 bar 可以访问包括a 的词法范围。我们可以使用foo() 的返回值制作多个项目,这很棒!然而,幕后究竟发生了什么。

函数返回的是对原始变量的引用……还是一些隐藏的副本?究竟发生了什么?

【问题讨论】:

标签: javascript


【解决方案1】:

变量a仍在被函数bar引用。

【讨论】:

    【解决方案2】:

    要了解闭包,您需要了解嵌套范围。 每个函数都有自己的范围,将其视为其私有空间,它可以访问外部但函数外部无法访问函数的私有范围。 当 foo 被执行时,处理器尝试在 foo 的本地范围内寻找一个名为“a”的变量,如果找到一个很好的,它就会使用它;如果没有,它会在链中查找名为 a 的变量,依此类推,直到它到达全局范围。 在这个例子中,变量“a”在上面的函数中找到,它被使用 请注意,即使您设置了

    var a =3;
    

    在全局范围内,bar函数执行还是会打印2,

    【讨论】:

    • 这不太对。这意味着查找是基于每个函数对象的运行时状态。它是静态作用域的。您所描述的基本上是with 声明。问题是你说 when 函数被执行。也许这不是您的意思,但考虑到原型的工作原理,至少可以说令人困惑。
    • @AluanHaddad 静态查找只是一种优化,它会导致相同的结果。正如您所观察到的,它甚至并不总是可能的,例如当涉及对象记录或eval
    • 我的意思是没有状态依赖的作用域链遍历。有一个从bar 到符号a 的映射,正如在某个外部范围中定义的那样。当 bar is 创建时,哪个外部范围是固定的。
    • @AluanHaddad 正如我的第一句话所暗示的,我是在描述查找链,提到执行并不一定意味着执行上下文与范围不同,这是一种逐步解释算法的方法用于确定函数中变量的值。如果这似乎仍然是错误的,请赐教
    【解决方案3】:

    函数返回的是对原始变量的引用……还是一些隐藏的副本?究竟发生了什么?

    基本上,是的。返回的函数带有它的封闭范围,其中包括该范围内的变量。它不是那些变量的副本——它是作用域本身。这就是闭包的本质。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 2020-05-16
      相关资源
      最近更新 更多