无法理解Javascript闭包示例

时间:2017-10-20 00:51:19

标签: javascript function closures

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

这是他们给出的解释:

  

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

实际代码:

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;

有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:2)

  1. 为什么obj.someVar++会更改最后两行的结果?

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

  2. 为什么以下添加的num ++不会将最后两个num结果更改为8和9而不是7和8?

    由于您使用了关键字num,因此var变量与外部变量不同。 JavaScript是功能范围的,它们指的是不同的值。

  3. 我可以看到混乱的来源。您尝试传递someNumsomeRef并对其执行“相同”操作(增量),但您有不同的行为。

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

    • 对于num,将复制值4
    • 对于obj,将复制值,在本例中为参考值。

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