ES6: 迭代器与生成器
什么是迭代器?
迭代器是一个对象,它拥有一个next方法,调用next方法会返回一个对象,该对象有两个属性值,value和done。每次调用next方法,返回的value表示可迭代对象中的下一个值,done表示迭代是否完成。根据此定义,可用下面的代码实现一个迭代器:
let create_iter = function(items) {
let i = 0;
return {
next: function() {
let value, done;
if (i >= items.length) {
value = null;
done = true;
} else {
value = items\[i++\];
done = false;
}
return {
value: value,
done: done
}
}
}
}
什么是生成器?
用来创建迭代器的函数称之为生成器,ES6为了简化生成器,引入了新的语法:
- 在生成器函数前加*
- 使用yield关键字抛出下一个value
引入新的语法后,生成器的代码可以简化为:
let gen = function*(items) {
for (let i = 0; i < items.length; i++) {
yield items\[i\];
}
}
举个栗子
下面的代码比较了两种创建迭代器的方法:
let create_iter = function(items) {
let i = 0;
return {
next: function() {
let value, done;
if (i >= items.length) {
value = null;
done = true;
} else {
value = items[i++];
done = false;
}
return {
value: value,
done: done
}
}
}
}
let gen = function*(items) {
for (let i = 0; i < items.length; i++) {
yield items[i];
}
}
let items = [1, 2, 3, 4, 5];
let it = gen(items);
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
输出结果:
$ node test.js
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
生成器的表现形式
- function *my_generator(items) {}
- let my_generator = function *(items) {}
- let obj = {*my_generator(items){}};
可迭代对象
可迭代对象指的是包含Symbol.iterator属性的对象,数组、Set、Map、字符串都是可迭代对象,都有默认的迭代器。 可迭代对象可以与for-of配合使用,例如:
let numbers = [1, 2, 3, 4, 5];
for (let num of numbers) {
console.log(num);
}
可以用一下方法自定义一个可迭代对象:
let colors = {
items: [1, 2, 3, 4, 5],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
}
内置迭代器
数组、Map和Set 都有一下三个内置的迭代器:
- entries(): 返回一个包含键值对(数组)的迭代器
- values(): 返回一个只包含值的迭代器
- keys(): 返回一个只包含键的迭代器
对于数组来说,keys返回的是元素的下标,对于Set来说,返回的是元素的值,而对于Map来说,返回的是元素的key。
给迭代器传入参数
当调用next方法时,若传入参数,则该参数会替代上一次yield表达式的值,例如:
let gen = function *() {
let a = yield 1;
let b = yield a + 1;
yield b + 1;
}
let iter = gen();
console.log(iter.next());
console.log(iter.next(100));
console.log(iter.next(200));
console.log(iter.next());
执行结果:
$ node test.js
{ value: 1, done: false }
{ value: 101, done: false }
{ value: 201, done: false }
{ value: undefined, done: true }
#### 生成器委托
也就是生成器的嵌套,例如:
let generator0 = function *() {
yield 0;
yield 1;
yield 2;
}
let generator1 = function *() {
yield 3;
yield 4;
yield 5;
}
let generator = function *() {
yield *generator0();
yield *generator1();
yield 6;
}
let iter = generator();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 三木的技术博客!
评论