2016-12-30 56 views
2

所以我有一個情況,我有一個應該從數組返回值的生成器函數,但是數組正在填充在消耗生成器輸出的同一個循環中。如果在迭代過程中添加基礎集合,是否定義了數組迭代器的行爲?

具體場景是一個生成器,用於返回自動密鑰密碼的密鑰序列,其中每個新解碼的字符都附加到密碼密鑰的末尾。我的實現有效,但我不確定它是否能夠正常工作,或者這是一個未定義行爲的例子,它恰好對我有利。基本上,下面的代碼必須總是打印「a」,「b」,「c」,「d」,「e」,或者對於實現打印「a」,「b」 「c」,「undefined」,「undefined」?我總是很想修改一個正在迭代的集合。

let a = ["a", "b", "c"]; 
let iter = function*() { yield* a; }(); 
console.log(iter.next().value); // "a" 
console.log(iter.next().value); // "b" 
a.push("d"); 
a.push("e"); 
console.log(iter.next().value); // "c" 
console.log(iter.next().value); // "d" - but is this guaranteed? 
console.log(iter.next().value); // "e" - or is it? 

編輯:從談論「發電機」改變了標題爲「迭代器」,以更準確地反映問題

+0

我認爲你需要在你的生成器開始時複製一個a,然後''*'給拷貝。 – user949300

+1

是的,ES6爲所有集合處理突變指定了@@ iterator()的行爲。 – Bergi

回答

2

的真正的肉據ES6 &超越,由凱爾·辛普森,頁。 103,yield *需要可迭代,並「調用該迭代的迭代器」。所以你真的在詢問可迭代的行爲,而不是生成器的行爲。

我很難找到官方規範的數組迭代器如何在底層數組被修改時作出反應,但我必須假設這樣一個基本功能是正確實現的 - 即,根據您的實驗,新的數組元素被包含在迭代中。當然,除非你使用IE6。 :-)

因此,如果你想要你的發生器只包含a[]的原始元素,你必須複製一份。例如

let iter = function*(a) { 
    let copy = Array.from(a); 
    yield * copy; 
} 
+0

感謝您對術語的更正!你是對的,我的問題真的是可迭代的行爲。我實際上得到了我想要的結果(我希望它能夠產生包括新增功能在內的所有元素),但我一直對這種行爲是否被規範定義好了感到好奇。從Bergi的評論中,現在我已經找到了正確的東西(數組迭代器,而不是生成器行爲),我發現%ArrayIteratorPrototype%.next()應該總是評估當前的長度(http://www.ecma-international。組織/ ECMA-262/6.0 /#仲%arrayiteratorprototype%的.next) – PMV