[英]Double let declaration: How does let hoisting work in for loops?
鑒於以下簡化代碼,為什么我會得到一個ReferenceError?
function foo(n){
for (let i = 0; i < n; i++) {
console.log(i);
let i = 10;
}
}
foo(4);
// OUTPUT: ReferenceError: i is not defined
let
變量應該像所有其他類型的聲明一樣被提升。 因此,在此代碼中, i
被聲明兩次。 首先,在初始化關閉和第二個for循環本身。
為什么i is not defined
此輸出i is not defined
而不是Identifier 'i' has already been declared
了Identifier 'i' has already been declared
。
JS如何閱讀上面的代碼?
let
變量應該像所有其他類型的聲明一樣被提升。
let
變量沒有懸掛,不同var
變量和函數和類的聲明。 const
變量是相同的。
變量在到達聲明它的行之前不會存在。
但是 ,在到達聲明之前,您無法訪問相關范圍中的變量。 這有點無益,被稱為時間死區 。 ( 有用的2ality博客 )
這很有用,因為在聲明變量之前訪問它幾乎總是一個錯誤。 或者,至少,它是令人困惑的,並會在您重構時導致錯誤。
function foo(n){
for (let i = 0; i < n; i++) {
// i cannot be accessed
let i = 10;
// i is set to 10
}
}
foo(4);
至於為什么它不是“已經聲明的標識符”錯誤, for
循環標頭中聲明的變量的范圍是與塊中聲明的變量的單獨變量。 這段代碼中基本上有三個范圍:外部的一個,一個在for
循環標題中開始,另一個在用{}
包圍的塊中開始。
累計到MDN:
function test(){
var foo = 33;
if (true) {
let foo = (foo + 55); // ReferenceError
}
}
test();
由於詞法作用域,表達式(foo + 55)中的標識符“foo”評估為if塊的foo,而不是值為33的上覆變量foo。在那一行中,if塊的“foo”已經已經在詞法環境中創建,但尚未達到(並終止)其初始化(這是語句本身的一部分):它仍然處於時間死區。
這意味着如果循環變量在您的示例中是“讀取”,(在您的情況下是console.log,您無法將其分配給同名的var,就像在“死區”中一樣)
MDN ref: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let (在臨時死區下 )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.