我个人认为迭代器和生成器是 es6 新增的特性里面,非常重要的部分,充分地掌握和使用迭代器和生成器,是十分必要和重要的,所以我会写关于二者的一系列文章。话不多说,先来了解一下基本概念:
一:什么是迭代器
1: 迭代器是一个对象
2: 迭代器有一个属性:next()方法,它的返回值是一个对象,我姑且叫它‘next 返回对象’,以便在下文使用
3:’next 返回对象有 2 个属性:value 和 done
4:’next 返回对象‘的 value:表示迭代器的数据集里面下一个将要返回的值
5:’next 返回对象‘的 done:如果这轮调用 next(),有数据返回,那么 done 为 false;如果这轮调用 next(),已经没有可返回的数据了,done 为 true,相应地 value 为 undefined
根据以上描述,我们可以用 ES5 的语法创建一个方法,这个方法的参数是一个数组,返回值是一个迭代器对象:
function createIterator(items) {
var i = 0;
return {next: function () {
var done = i >= items.length;
var value = done ? undefined : items[i++];
return {
value: value,
done: done
}
}
}
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next());//{value: 1, done: false}
console.log(iterator.next());//{value: 2, done: false}
console.log(iterator.next());//{value: 3, done: false}
// 没有更多可返回的值
console.log(iterator.next());//{value: undefined, done: true}
二:什么是生成器
在上面的内容里我们了解到了什么是迭代器,并且根据迭代器的定义用 es5 的语法自己创建了一个生成迭代器的方法:createIterator()。在 es6 里面呢,我们不用再手动创建这个 createIterator()方法,生成器 就是用来做这个工作的。照旧,我们来看看生成器的具体定义和语法:
1: 生成器是一个函数
2: 生成器返回迭代器
3: function 关键字后面紧挨着或者留一个空格后,必须有一个星号(*)4: 函数体里面会用到关键字 yield,来依次返回想要迭代的值
根据上面的定义,我们来使用生成器创建一个迭代器,取代前面的 es5 的语法:
function* createIterator() {
yield 1;
yield 2;
yield 3;
}
let iterator = createIterator();
console.log(iterator.next());//{value: 1, done: false}
console.log(iterator.next());//{value: 2, done: false}
console.log(iterator.next());//{value: 3, done: false}
// 没有更多可返回的值
console.log(iterator.next());//{value: undefined, done: true}
以上,我们就用生成器创建了一个迭代器,生成器创建的迭代器会按照 yield 语句的顺序,依然返回迭代的值。当然这个例子与我们前面的 es5 的例子,并不是完全一样,这里我们没有传入参数,而是方法体里面写死了迭代的值。当然我们也可以传入参数:
function* createIterator(items) {for(let i = 0; i < items.length; i++){yield items[i];
}
}
三:生成器函数表达式
生成器函数拥有一般函数的特性,所以也可以通过函数表达式来创建生成器:
let createIterator = function* (items) {for (let i = 0; i < items.length; i++) {yield items[i];
}
};
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); //{value: 1, done: false}
console.log(iterator.next()); //{value: 2, done: false}
console.log(iterator.next()); //{value: 3, done: false}
// 没有更多可返回的值
console.log(iterator.next()); //{value: undefined, done: true}
这里要特别注意的是,不能使用箭头函数创建生成器。
四:yield 的使用限制
1: yield 关键字只能用在生成器函数内
2: 第一条所说的生成器函数内,是指最近一层的函数作用域是生成器函数。
看一个例子:
function* createIterator(items) {items.forEach(function (item) {
// 语法错误
yield item;
})
}
上面这个例子里,最外层的函数数一个生成器。但是离 yield 最近一层的函数是 forEach()里面的 function,而这个 function 不是一个生成器函数,所以这里使用 yield,依然会导致语法错误。
以上就是关于迭代器和生成器的基本概念,怎么创建迭代器和生成器,以及使用中一些需要特别注意的点。