2017-10-20 254 views
0

我明白關閉的大部分內容,但後來這個例子讓我頗爲困惑。我將發佈兩個代碼示例:第一個是原始引用,他們解釋了關閉的工作原理,第二個代碼是我添加內容的代碼,但沒有給出我期望的結果。麻煩理解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; 

有人可以解釋這一點嗎?

回答

2
  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及其所有細節。再次感謝您的迴應。 –