2009-11-23 86 views
0

我的問題實際上更多的是關於JavaScript中的範圍,而不是關閉。JavaScript中的範圍和閉包問題

讓我們以下面的代碼:

var f = function() { 
    var n = 0; 
    return function() { 
     return n++; 
    }; 
}(); 

console.log(f()); 
console.log(f()); 

上面的代碼輸出:

0 
1 

正如你可以從上面的代碼中看到,f(自調用)返回一個函數,創建關閉n


因此,它可以使用匿名函數;因此,我然後用命名函數試了一下:

var f2 = function() { 
    return n++; 
}; 

var f = function() { 
    var n = 0; 
    return f2; 
}(); 

console.log(f2()); // <= [n is not defined] 

上面的代碼不工作,與錯誤n is not defined。我認爲這是一個範圍界定問題;但我不明白爲什麼;

爲什麼範圍與匿名內部函數相同,但不能與命名的外部函數一起使用?

另外,在第二個例子中,我是否創建了一個閉包?

回答

4

在第一個示例中創建閉包,因爲匿名函數中的代碼使用在匿名函數之外聲明的局部變量。

在第二個示例中,函數f2n變量的範圍已經在函數聲明時決定。使用相同名稱創建局部變量不會改變函數的含義,並且在另一個函數中使用該函數不會改變它的作用域。因此,該函數不使用局部變量。

2

沒有辦法爲F2找出它應該採取變量n。

在第一個例子中,匿名函數在函數f中,在第二個 - 外部(f2而不是匿名)。所以,f2不能訪問變量n,因爲它在另一個範圍內並且不可訪問(不可見)。試試把f2聲明放在內。

0

在你的第二個例子中,你不是創建一個閉包,而是簡單地返回一個全局變量。 f2沒有被關閉,因爲它在更一般的(在這種情況下是全局的)範圍中被聲明,並且n在更具體的範圍中被聲明。在範圍鏈「漏斗」下關閉是不可能的,並且只有在所有相關實體在相同範圍內定義時纔有效。

0

,我們可以把你的第二個例子,使其與命名函數工作:

var f = function() { 
    var n = 0; 
    var f2 = function() { 
     return n++; 
    }; 
    return f2; 
}(); 
console.log(f()); 
console.log(f()); 

這將輸出,0和1爲你的第一個例子。正如其他答案所述,它不是關於被命名或匿名的函數,而是關於n和f2的範圍。由於您在示例中聲明瞭f之外的f2,因此它無法訪問f範圍內聲明的變量n。