2016-01-10 51 views
11

考慮下面的代碼片段爲什麼「的(一個的)」正確地迭代的陣列?

var a = [1, 2, 3, 4]; 
for (a of a) { // The first 'a' is made by mistake 
    console.log(a); 
} 

for循環的第一a被錯誤寫入。我想上面的代碼應該運行錯誤,因爲當a在第一次迭代被分配到1,然後a迭代的對象。所以在下一次迭代中應該拋出一個錯誤。

實際上,研究結果如下:

1 
2 
3 
4 

看來上面的代碼可以正確地遍歷該陣列。在for循環後,a結果是4爲什麼?

> a 
4 

對於進一步的調查,我試圖從ECMA-6 doc找了一些資料,但我通過下面的語句混淆。

爲(AssignmentExpression的變種ForBinding)聲明

爲(AssignmentExpression的ForDeclaration)聲明

要理解ForBindingForDeclaration,測試下面的代碼。

var a = [1, 2, 3, 4]; 
for (var a of a) { 
    console.log(a); 
} 
console.log(a); 

不幸的是,結果與以前的代碼相同。是什麼for (var a in a)for (a in a)之間的區別?

回答

9

for評估「AssignmentExpression」的值並對其進行迭代。在迭代開始時所獲得的值只有一次,因此重複使用相同的變量是完全有效的(也相當混亂)。

var存在:for (a of ...)for (var a of ...)不作出任何代碼區別,你已經有a定義 - 所以它只是重新申報相同的變量。


要完全精確有些情況下的行爲是不同的情況 - 當a在當前功能var版本將跟隨該值(如JavaScript的外部範圍中聲明的所有var語句被提升到功能範圍的頂部):

var a = [1,2,3]; 
function tryForVar() { 
    // Note that declaration of `a` is hoisted here as var a = undefined; 
    // for (var a ... does not work as expected as local 'a' is undefined 
    for (var a of a) { 
    console.log(a); // log 'undefined' once 
    } 
    console.log(a); // undefined 
} 
tryForVar(); 
console.log(a); // [1,2,3] 

function tryFor() { 
    // Note that declaration of `a` from outer scope 
    // for (a ... works fine as it uses outer 'a' 
    for (a of a) { 
    console.log(a); // logs all 1,2,3 in sequence 
    } 
    console.log(a); // 3 
} 
tryFor(); 
console.log(a); // 3 
+0

這似乎是真正解決這個問題,似乎也是唯一正確的答案是唯一的答案。不知道爲什麼別人給它一個downvote。從我+1。 – jfriend00

+6

我沒有投下來,但'var'聲明的變量沒有被重新申報。聲明在他們的範圍內被提起,並且在代碼後面會遇到'var's _ignored_。 – Teemu

+1

@Teemu是的,我的陳述確實是過於簡單化了,而應該是「如果你使用'var a'版本,在循環之前和之後'a'的含義仍然是相同的,但是它可能會因爲懸掛而影響來自外部範圍的變量(並因此完全改變你正在迭代的內容)「。 –

相關問題