JavaScript 迭代器與生成器

1、什麼是迭代器:

當一個對象可以當成迭代器時候;它要擁有以下定義:

滿足上述定義就是一個迭代器:迭代器是一個對象!

function makeIterator(array){
    var nextIndex = 0;
    
    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
}

var it = makeIterator(['yo', 'ya']);

console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done);  // true

函數 makeIterator 返回的就是一個迭代器對象。

2、可迭代協議

當一個對象可以被 for of 遍歷到,[...]展開符 展開;
它必須有一個[Symbol.iterator]方法(或者原型鏈上);該方法定義被迭代的行爲,即返回什麼類型的數據,
該方法放回的是一個對象,被返回的對象要符合迭代器協議。上面的 makeIterator 就可以作爲一個對象的[Symbol.iterator]方法;因爲它返回了一個對象,並且符合迭代器協議。(返回的就是迭代器對象)


翻譯一下就是 一個對象是可迭代的(for of [...])他必須有一個[Symbol.iterator]方法返回一個迭代器。

function makeIterator(){
    var nextIndex = 0;
    var array= [1,2,4,5,6,7,8,9,10]
    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
}
var s = {a:1,b:2,c:3};//對象不是可迭代對象
s[Symbol.iterator]=makeIterator;//實現Symbol.iterator 方法
for (var x of s){
console.log(x)
}
//可以使用迭代for of 循環
1 debugger eval code:2:1
2 debugger eval code:2:1
4 debugger eval code:2:1
5 debugger eval code:2:1
6 debugger eval code:2:1
7 debugger eval code:2:1
8 debugger eval code:2:1
9 debugger eval code:2:1
10

3、默認的可迭代對象

字符串是可迭代對象
for ( var i of 'string'){
console.log(i)
}
s debugger eval code:2:1
t debugger eval code:2:1
r debugger eval code:2:1
i debugger eval code:2:1
n debugger eval code:2:1
g
var s = ('string')[Symbol.iterator]()
s  // String Iterator {  } //返回的s是迭代器對象
[...s]  //對象展開符 Array(6) [ "s", "t", "r", "i", "n", "g" ]
數組、map、 set 都是可迭代的對象
var ss = ([1,2,3,4,5])[Symbol.iterator]()
//undefined
ss
//Array Iterator {  }

4、生成器

顯示的維護對象的狀態不太方便(迭代器需要next方法,並且返回對象中要有value、done屬性);生成器可以很好的做到這一點。
使用function* 的形式定義生成器函數;返回一個生成器對象。

function* generator(i) {
  yield i;
  yield i + 10;
}

var gen = generator(10);

console.log(gen.next().value);
// expected output: 10

console.log(gen.next().value);
// expected output: 20

使用yield 拋出結果;惰性求職;並且自動維護對象狀態;不需要手動維護對象狀態。

調用一個生成器函數並不會馬上執行它裏面的語句,而是返回一個這個生成器的 迭代器 (iterator )對象。 MDN

或者如果用的是 yield*(多了個星號),則表示將執行權移交給另一個生成器函數(當前生成器暫停執行) 移交代碼控制權

next方法傳參:

調用 next()方法時,如果傳入了參數,那麼這個參數會作爲上一條執行的 yield 語句的返回值,例如:

function *gen(){
    yield 10;
    y=yield 'foo';
    yield y;
}

var gen_obj=gen();
console.log(gen_obj.next());// 執行 yield 10,返回 10
console.log(gen_obj.next());// 執行 yield 'foo',返回 'foo'
console.log(gen_obj.next(10));// 將 10 賦給上一條 yield 'foo' 的左值,即執行 y=10,返回 10
console.log(gen_obj.next());// 執行完畢,value 爲 undefined,done 爲 true
yield*
function* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function* generator(i){
  yield i;
  yield* anotherGenerator(i);// 移交執行權
  yield i + 10;
}

var gen = generator(10);

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

參考鏈接 :https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols#iterable

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章