[js高手之路] es6系列教程 - 迭代器與生成器詳解


什么是迭代器?

迭代器是一種特殊對象,這種對象具有以下特點:

1,所有對象都有一個next方法

2,每次調用next方法,都會返回一個對象,該對象包含兩個屬性,一個是value, 表示下一個將要返回的值。另一個是done,他是一個布爾值,用來表示該迭代器是否還有數據可以返回.

3,迭代器還會保存一個內部指針指向當前集合中的值

設計模式中有個迭代模式,跟迭代器是差不多的,我之前有寫過2篇文章關於迭代模式:

[js高手之路] 設計模式系列課程 - 迭代器(1)

[js高手之路] 設計模式系列課程 - DOM迭代器(2)

 

用es5的方式,封裝一個迭代器:

 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();

這種使用方式會報錯,下面這種使用,也會報錯

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 }

也可以用對象的簡寫方式:

 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 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM