2016-07-28 50 views
1
function f1() {     
    var n = 999;     
    nAdd = function() { 
     n += 1 
    }     
    function f2() {       
     alert(n);     
    }     
    return f2;   
}   
var result1 = f1(); 
var result2 = f1(); 
var result3 = f1();   

nAdd(); 
result1(); //999 
result2(); //999 
result3(); //1000 

想想這個代碼示例,我得出的結論是,調用nAdd()隻影響最接近它的閉包。JavaScript closure - 爲什麼只有result3()的輸出受nAdd()影響?

例如:result3()的輸出是1000.
爲什麼?

回答

1

它與nAdd被賦予的功能有關。請注意,當您創建閉包時,會創建局部變量的新副本(缺少更好的單詞)。因此,result1n不同於result2n,它不同於result3n。他們是分開的,每個關閉不能訪問另一個關閉的n

看這句話:

nAdd = function() { 
    n += 1; 
} 

這種分配nAdd每次新的閉包。每次,這次關閉只會影響最近的「複製」n

所以,當你在做。

var result1 = f1(); // assign nAdd for the first time, referring to result1's n. 
var result2 = f1(); // re-assign nAdd, now it affects result2's n. 
var result3 = f1(); // re-assign nAdd, now it affect result3's n. 

nAdd每次都被分配一個新的關閉。最後一次,nAdd被授予封閉與result3的副本。

因此,當你做nAdd(),你只增加result3n

下面是一個可能會清除問題的示例。

function f1() {     
    var n = 999;     
    nAdd = function() { 
     n += 1 
    }     
    function f2() {       
     alert(n);     
    }     
    return f2;   
}   
var result1 = f1(); 
var nAdd1 = nAdd; 
var result2 = f1(); 
var nAdd2 = nAdd; 
var result3 = f1();   
var nAdd3 = nAdd; 

nAdd3(); 
result1(); //999 
result2(); //999 
result3(); //1000 
nAdd1(); 
result1(); // 1000 
nAdd1(); 
result1(); // 1001 
nAdd2(); 
result2(); // 1000 
nAdd(); 
result3(); // 1001 (the most recent nAdd result3's n). 

爲了進一步詳細描述,可以考慮,如果你這樣做,而不是會發生什麼:

var result1 = f1(); 
nAdd(); 
var result2 = f1(); 
var result3 = f1();  

result1(); // 1000 
result2(); // 999 
result3(); //999 

或者這樣:

var result1 = f1(); 
var result2 = f1(); 
nAdd(); 
var result3 = f1();  

result1(); // 999 
result2(); // 1000 
result3(); // 999 

可以很明顯看出nAdd更新只有最近調用的n 。!

+0

「這個賦值n每次都添加一個新函數,每次這個函數只會影響n的最新副本。爲什麼函數隻影響n的最新副本? – Tommy

+0

@Tommy每次創建一組新的局部變量。將閉包分配給nAdd時,閉包指向最近一組局部變量。但是,每次調用函數時都會覆蓋nAdd。從而。 nAdd僅指最近調用的變量(您分配給result3),因此它隻影響result3的n。嘗試將nAdd調用移至分配給result3之前,並查看它如何影響您的輸出! –

+0

@GiorgianThanks!你的回答和Elune的回答都很好!我想我會處理它。 – Tommy

0

首先,您需要清楚以下事情:

nAdd是一個全局作用域函數。但它使用了一個局部範圍變量n。

每次您重新創建f1()時,nAdd函數的指針都會改變。

最後它會變成最接近的f1()閉包,nAdd函數中的n變量也會指向最接近的f1()閉包。所以它只能改變最接近的值。

+0

謝謝! 'nAdd函數的指針將會改變。'是如此重要,我處理它! – Tommy

相關問題