麻烦理解Javascript关闭示例

问题描述:

我明白关闭的大部分内容,但后来这个例子让我颇为困惑。我将发布两个代码示例:第一个是原始引用,他们解释了关闭的工作原理,第二个代码是我添加内容的代码,但没有给出我期望的结果。麻烦理解Javascript关闭示例

这是他们给出的解释是:

最后一个例子表明,每呼吁 局部变量创建一个单独的封闭。每个功能 声明没有单个关闭。每个函数调用都有一个闭包。

的实际代码:

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. 为什么obj.someVar++改变的结果的最后两行?

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

  2. 为什么下面的另外的num ++不是最后两个NUM结果更改为8和9,而不是7和8?

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


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

你必须认识到的一件事是num的值是一个原始值4,并且obj的值是一个引用(类似于C中的指针)。将参考视为指示内存地址的数字(但不完全是数字)。当你将它们传递到函数,值复制:

  • num,价值4被复制。
  • 对于obj,复制该值(在本例中为参考)。

由于复制引用不创建一个新的对象,当你改变函数外部的值obj.someVar,这些变化将在功能上体现,因为它仍然指的是同一个对象。

+0

令人惊讶的是,我现在明白了。谢谢! –

+1

我真的开始享受Javascript及其所有细节。再次感谢您的回应。 –