重寫迭代器方法需 ECMAScript 2015(ES6) , TypeScript 需 1.5 以上版本。函數
可迭代協議 容許 JavaScript 對象去定義或定製它們的迭代行爲, 例如(定義)在一個 for..of 結構中什麼值能夠被循環(獲得)。一些內置類型都是內置的可遍歷對象而且有默認的迭代行爲, 好比 Array or Map, 另外一些類型則不是 (好比Object) 。this
爲了變成可遍歷對象, 一個對象必須實現 @@iterator 方法, 意思是這個對象(或者它原型鏈prototype chain上的某個對象)必須有一個名字是 Symbol.iterator 的屬性:prototype
如下代碼所有使用 TypeScript, TypeScript 版本號爲 2.0.10, 使用 ES6 規範。code
var someArray = [1, 5, 7]; var someArrayEntries = someArray.entries(); console.log(someArrayEntries.toString()); // "[object Array Iterator]" console.log(someArrayEntries === someArrayEntries[Symbol.iterator]()); // true console.log([...someArray] ); //[1,5,7] let iterator = someArrayEntries[Symbol.iterator](); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); //[Symbol.iterator] 返回一個對象的無參函數,被返回對象需符合迭代器協議。
someArray[Symbol.iterator] = ()=>{ return { _index:0, next: function() { if(this._index < someArray.length ){ return { value: someArray[this._index++], done: false} }else{ return { value: undefined, done:true} } }, [Symbol.iterator]:()=>{ return this; } }; }; //在js文件中,能夠省略掉對 [Symbol.iterator] 屬性的定義。 //next() 返回的數據中, //done爲布爾值,按照約定應爲是否已經進行到函數邊界的描述 //value 則爲當前可迭代對象的某個屬性值。在js文件中, done爲true 可省略。但實際上,value能夠爲任何js對象 let someArrayIterator = someArray[Symbol.iterator](); console.log(someArrayIterator.next()); //{ value: 1, done: false } console.log(someArrayIterator.next()); //{ value: 5, done: false } console.log(someArrayIterator.next()); //{ value: 7, done: false } console.log(someArrayIterator.next()); //{ value: undefined, done: true } console.log(someArrayIterator.next()); //{ value: undefined, done: true } someArrayEntries[Symbol.iterator] = ()=>{ return { _index:0, next: function() { if(this._index < someArray.length){ return { value: [this._index,someArray[this._index++]], done: false} }else{ return { value: [this._index,undefined], done:true} } }, [Symbol.iterator]:()=>{ return this; } }; }; console.log(someArrayEntries === someArrayEntries[Symbol.iterator]()); //false iterator = someArrayEntries[Symbol.iterator](); console.log(iterator.next()); //{ value: [ 0, 1 ], done: false } console.log(iterator.next()); //{ value: [ 1, 5 ], done: false } console.log(iterator.next()); //{ value: [ 2, 7 ], done: false } console.log(iterator.next()); //{ value: [ 3, undefined ], done: true } console.log(iterator.next()); //{ value: [ 3, undefined ], done: true }
for(let obj of someArray){ console.log(obj); } // 1 5 7 let someArrayIterator = someArray[Symbol.iterator](); let obj = someArrayIterator.next(); while(!obj.done){ console.log(obj.value) obj = someArrayIterator.next(); } // 1 5 7 //這裏使用 while 來 模擬一部分 for...of 的邏輯。 console.log([...someArray] ); // [ 1, 5, 7 ] console.log([...someArrayEntries]);//[ [ 0, 1 ], [ 1, 5 ], [ 2, 7 ] ] //內置可迭代對象皆可以使用上述2種語法進行遍歷其鍵值對。 //String, Array, TypedArray, Map and Set 是內置可迭代對象, 由於它們的原型對象都有一個 @@iterator 方法。 //除此以外由用戶本身實現的 @@iterator 方法也可使用上述2中語法。
function* 聲明 (function關鍵字後跟一個星號)定義了一個生成器函數 (generator function),它返回一個 Generator 對象。對象
注意:箭頭函數 沒法做爲生成器函數。接口
生成器ip
>生成器是一種能夠從中退出並在以後從新進入的函數。生成器的環境(綁定的變量)會在每次執行後被保存,下次進入時可繼續使用。
yield原型鏈
>yield 關鍵字用來暫停和恢復一個生成器函數 ( (function* 或 legacy generator).
yield*generator
>yield* 能夠把須要 yield 的值委託給另一個生成器或者其餘任意的可迭代對象。
function* anotherGenerator(i) { yield i + 1; //yield 會返回當前語句的值,相似於return。但在生成器函數中,return受到使用限制。 yield i + 2; yield i + 3; } function* generator(i){ yield i; yield* anotherGenerator(i); yield i + 10; } var gen = generator(10); //執行生成器函數會返回一個生成器,保存了當前函數運行環境上下文,同時定義了next()方法來恢復函數運行直至下一條yield語句。 console.log(gen.next().value); // 10 console.log(gen.next().value); // 11 console.log(gen.next().value); // 12 console.log(gen.next().value); // 13 console.log(gen.next().value); // 20 //使用生成器函數來實現迭代功能,很顯然比以前實現 Iterator 系列接口要方便快捷的多。