ES6中的迭代器和生成器

mac2024-08-04  53

迭代器

所有迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true。

ES5中模拟一个迭代器:

function createIterator(items) { var i = 0; return { next: function() { var done = (i >= items.length); var value = !done ? items[i++] : underfined; return { done: done, value: value }; } }; } 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: true} console.log(iterator.next); // {value: underfined, done: true}

生成器

生成器是一种返回迭代器的函数,通过 function 关键字后的星号(*)来表示,函数中会用到新的关键字yield。yield 关键字是ES6的新特性,可以通过它来指定调用迭代器的next()方法时的返回值及返回顺序。每当执行完一条yield语句后函数就会自动停止执行,直到再次调用迭代器的next()方法才会继续执行下一个yield。使用yield关键字可以返回任何值或表达式。 function* createIterator(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关键字只可在生成器内部使用,在其他地方使用会导致程序抛出语法错误。如:

function* createIterator(items) { items.forEach(function(item) { // 语法错误 yield item + 1; }) }

可迭代对象(扩展)

可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。Symbol.iterator通过指定的函数可以返回一个作用于附属对象的迭代器。

由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象。在ES6中所有集合对象、字符串都是可迭代对象。

let values = [1, 2, 3]; let iterator = values[Symbol.iterator](); 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 }

创建可迭代对象

默认情况下,开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,则可以将其变为可迭代对象

let collection = { items: [], * [Symbol.iterator]() { for (let item of this.items) { yield item; } } }; collection.items.push(1); collection.items.push(2); collection.items.push(3); for (let x of collection) { console.log(x); } // 1 // 2 // 3

内建迭代器(扩展)

在ES6中对集合对象都内建了三种迭代器(数组、Set、Map)。

entries() 返回一个迭代器,其值为多个键值对。values() 返回一个迭代器,其值为集合的值。keys() 返回一个迭代器,其值为集合中的所有键名。

在for-of循环中,数组和Set默认是values(),Map默认是entries()

let colors = ['red', 'green', 'blue']; for (let entry of colors.entries()) { console.log(entry); // [ 0, 'red' ] [ 1, 'green' ] [ 2, 'blue' ] } // 其余的就不一一举例了,有兴趣的自行体验

给迭代器传递参数(扩展)

如果给迭代器的next() 方法传递参数,则这个参数的值就会代替生成器内部上一条yield语句的返回值。

第一次调用next() 方法前不会执行任何yield语句,因此在第一次调用next()方法时传递参数是毫无意义的。

function* createIterator() { let first = yield 1; let second = yield first + 2; // 4+2 yield second + 3; // 5+3 } let iterator = createIterator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next(4)); // { value: 6, done: false } console.log(iterator.next(5)); // { value: 8, done: false } console.log(iterator.next()); // { value: undefined, done: true }
最新回复(0)