什麼是迭代器?
迭代器是一種特殊對象,這種對象具備如下特色:
1,全部對象都有一個next方法
2,每次調用next方法,都會返回一個對象,該對象包含兩個屬性,一個是value, 表示下一個將要返回的值。另外一個是done,他是一個布爾值,用來表示該迭代器是否還有數據能夠返回.
3,迭代器還會保存一個內部指針指向當前集合中的值
設計模式中有個迭代模式,跟迭代器是差很少的,我以前有寫過2篇文章關於迭代模式:
[js高手之路] 設計模式系列課程 - 迭代器(1)
[js高手之路] 設計模式系列課程 - DOM迭代器(2)
用es5的方式,封裝一個迭代器:es6
1 function createIterator( arr ){ 2 var i = 0; 3 return { 4 next : function(){ 5 var done = ( i >= arr.length ); 6 var value = !done ? arr[i++] : undefined; 7 return { 8 done : done, 9 value : value 10 } 11 } 12 }; 13 } 14 15 var iterator = createIterator( [ 10, 20, 30 ] ); 16 console.log( iterator.next() ); // { done : false, value : 10 } 17 console.log( iterator.next() ); // { done : false, value : 20 } 18 console.log( iterator.next() ); // { done : false, value : 30 } 19 console.log( iterator.next() ); // { done : true, value : undefined }
而後你再看看是否符合咱們上面說的迭代器對象的特色.
有了迭代器的基礎以後,咱們就來看看,什麼是生成器?
生成器是一種返回迭代器的函數,經過function關鍵字後的星號( * )來表示,函數中會用到新的關鍵字yield. 星號能夠緊跟function後面 也能夠在function後面加個空格.設計模式
1 function *createIterator(){ 2 yield 10; 3 yield 20; 4 yield 30; 5 } 6 7 var iterator = createIterator(); 8 console.log( iterator.next() ); // { done : false, value : 10 } 9 console.log( iterator.next() ); // { done : false, value : 20 } 10 console.log( iterator.next() ); // { done : false, value : 30 } 11 console.log( iterator.next() ); // { done : true, value : undefined }
經過上面這段程序,你應該看出來了,結果跟咱們以前用es5實現的迭代器是差很少的。可是你在這個生成器函數中壓根就沒有看見next方法,done和value屬性。由於生成器函數內部實現了迭代器。重點要關注下這個yield關鍵字,它有什麼特色?
1,每當執行完一條yield語句,函數就會自動中止執行, 執行完yield 10以後,函數就會自動中止。
2,下一次調用next方法,就會執行yield 20,函數又會自動中止,
3,下一次調用next方法,就會執行yield 30,函數自動中止
4,下一次在調用,沒有能夠迭代的元素,value返回undefined
用yield關鍵字返回數組的當前值數組
1 function *createIterator( arr ){ 2 for( var i = 0, len = arr.length; i < len; i++ ) { 3 yield arr[i]; 4 } 5 } 6 var iterator = createIterator( [ 10, 20, 30 ] ); 7 console.log( iterator.next() ); // { done : false, value : 10 } 8 console.log( iterator.next() ); // { done : false, value : 20 } 9 console.log( iterator.next() ); // { done : false, value : 30 } 10 console.log( iterator.next() ); // { done : true, value : undefined }
使用yield關鍵字,須要注意的地方:
yield關鍵字只能在生成器內部使用,在生成器內部的函數使用也會報錯.函數
1 function show(){ 2 yield 10; 3 } 4 show();
這種使用方式會報錯,下面這種使用,也會報錯es5
1 function *createIterator( arr ){ 2 for( var i = 0, len = arr.length; i < len; i++ ) { 3 return function(){ 4 yield arr[i]; 5 } 6 } 7 }
生成器支持函數表達式的寫法,可是不支持箭頭函數設計
1 var createIterator = function *( arr ){ 2 for( var i = 0, len = arr.length; i < len; i++ ) { 3 yield arr[i]; 4 } 5 } 6 var iterator = createIterator( [ 10, 20, 30 ] ); 7 console.log( iterator.next() ); // { done : false, value : 10 } 8 console.log( iterator.next() ); // { done : false, value : 20 } 9 console.log( iterator.next() ); // { done : false, value : 30 } 10 console.log( iterator.next() ); // { done : true, value : undefined }
1 var createIterator = *( arr )=>{ 2 for( var i = 0, len = arr.length; i < len; i++ ) { 3 yield arr[i]; 4 } 5 }
1 var *createIterator = ( arr )=>{ 2 for( var i = 0, len = arr.length; i < len; i++ ) { 3 yield arr[i]; 4 } 5 }
上面這2種箭頭寫法是不支持的.
生成器能夠添加在對象中指針
1 var obj = { 2 createIterator : function *( arr ){ 3 for( var i = 0, len = arr.length; i < len; i++ ) { 4 yield arr[i]; 5 } 6 } 7 }; 8 var iterator = obj.createIterator( [ 10, 20, 30 ] ); 9 console.log( iterator.next() ); // { done : false, value : 10 } 10 console.log( iterator.next() ); // { done : false, value : 20 } 11 console.log( iterator.next() ); // { done : false, value : 30 } 12 console.log( iterator.next() ); // { done : true, value : undefined }
也能夠用對象的簡寫方式:code
1 var obj = { 2 *createIterator( arr ){ 3 for( var i = 0, len = arr.length; i < len; i++ ) { 4 yield arr[i]; 5 } 6 } 7 }; 8 var iterator = obj.createIterator( [ 10, 20, 30 ] ); 9 console.log( iterator.next() ); // { done : false, value : 10 } 10 console.log( iterator.next() ); // { done : false, value : 20 } 11 console.log( iterator.next() ); // { done : false, value : 30 } 12 console.log( iterator.next() ); // { done : true, value : undefined }
轉載於猿2048:➸[《[js高手之路] es6系列教程 - 迭代器與生成器詳解》][1]對象