【问题标题】:Why this is not a closure为什么这不是闭包
【发布时间】:2017-08-08 18:51:24
【问题描述】:

由于闭包是绑定到其词法环境的函数,我想知道为什么notAClosure 构造不是闭包:

let a = { b: 42 };
let notAClosure = ( param ) => { param.b++ };
let aClosure = () => { a.b++ };
notAClosure(a);

notAClosure 被调用时,我们通过引用将对象a 传递给它。这意味着现在在闭包内部我们可以访问外部范围 = 词法环境。 我对函数的命名是否正确? aClosure 是真正的闭包吗? notAClosure 真的不是闭包吗?如果是正确的 - 那为什么?

【问题讨论】:

  • 一个函数只有在访问定义在外部范围内的变量时才会形成一个闭包。 param 是一个局部变量,所以 notAClosure 不是一个闭包。所有函数都可以访问全局变量,因此如果 a 是全局变量,则 aClosure 并不是真正的闭包。
  • 为什么这对你很重要?是否存在您的代码存在差异的真实场景?这似乎纯粹是哲学上的。

标签: javascript


【解决方案1】:

你的变量命名是正确的。

notAClosure 的函数体实际上并不引用其自身范围之外的任何内容。函数aClosure确实引用了一个超出其自身范围的变量,即a

a 被传递给 notAClosure by-value-by-reference。这会将对a 的“值”引用置于notAClosure 的函数体的直接范围内,因为param 是一个参数。

aClosure内,本地范围内没有a;相反,该函数(强制)引用外部范围内的a。一个稍微复杂一点的例子,为了更清楚为什么它变成了一个闭包:

let x = (function() {
    let a = { b: 42 };
    return () => { a.b++; };
})();

x 分配给一个函数,该函数立即返回另一个函数。 x 在返回的 lambda 函数的闭包中“隐藏”a不可能在不调用 x 的情况下以任何方式访问 a,但 a 仍然存在于内存中,因为它可以在返回的 lambda 的外部范围内访问,因此也可以在范围内访问.

【讨论】:

    【解决方案2】:

    您的函数 aClosure 只是通过全局范围访问您的 a 变量,因此,它不是闭包,您可以在此示例中看到它实际上修改了 a.b 值:

    let a = { b: 42 };
    let aClosure = () => { a.b++ };
    
    console.log(a.b);   //42
    aClosure();
    console.log(a.b);   //43 
    

    如果你想更好地理解闭包,我推荐this book

    【讨论】:

    • 您能否参考任何包含“全局”术语的闭包定义?如果不是,那么外部作用域的全局性对于理解闭包有什么作用?
    • 如果我错了,请原谅,但是当函数、回调等可以访问其“自己的”值时,就会发生闭包。这里我展示了因为aClosure() 在全局范围内修改了 a.b 的值,所以它不是闭包。
    猜你喜欢
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 2013-10-31
    • 1970-01-01
    • 2018-12-01
    • 2020-01-03
    相关资源
    最近更新 更多