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