【问题标题】:Trouble understanding Javascript closure example无法理解 Javascript 闭包示例
【发布时间】:2017-10-20 09:18:07
【问题描述】:

我了解大多数闭包是什么,但是这个例子让我很困惑。我将发布两个代码示例:第一个将是他们解释闭包工作原理的原始引用,第二个将是我添加一些内容的代码,但它没有给我预期的结果。

这是他们给出的解释:

最后一个例子表明,每次调用都会创建一个单独的闭包 局部变量。每个函数没有一个闭包 宣言。每次调用函数都有一个闭包。

实际代码:

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

现在,我不明白为什么 obj.someVar++ 会更改最后两行的结果,并且以下添加 num++ 不会将最后两个 num 结果更改为 8 和 9 而不是 7 和 8。有什么区别?

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
num = 4
obj = {someVar: 4};
fn1 = newClosure(num, obj);
fn2 = newClosure(num+1, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
num++
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

谁能给我解释一下?

【问题讨论】:

    标签: javascript function closures


    【解决方案1】:
    1. 为什么obj.someVar++ 会改变最后两行的结果?

      因为函数中的ref是对对象的引用。您更改了 obj.someVar,因此以下日志反映了该更改。

    2. 为什么后面的num++加法没有把最后两个num结果改为8和9,而不是7和8?

      num 变量与外部变量不同,因为您使用了关键字var。 JavaScript 是函数范围的,它们引用不同的值。


    我可以看到混乱来自哪里。您尝试传递 someNumsomeRef 并对它们执行“相同”操作(增量),但您得到了不同的行为。

    你必须意识到的一点是num 的值是一个原始值4,而obj 的值是一个引用(类似于C 中的指针)。将引用视为指示内存地址的数字(但不完全是数字)。当您将它们传递给函数时,值会被复制:

    • 对于num,值4 被复制。
    • 对于obj,值(在本例中为引用)被复制。

    由于复制引用不会创建新对象,因此当您在函数外部更改值 obj.someVar 时,更改将反映在函数中,因为它仍然引用同一个对象。

    【讨论】:

    • 太棒了,我现在明白了。谢谢!
    • 我真的开始喜欢 Javascript 及其所有的小细节了。再次感谢您的回复。
    猜你喜欢
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2019-04-14
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 2013-03-03
    相关资源
    最近更新 更多