function idMaker(){ var index = 0; return { next: function(){ return {value: index++, done: false}; } } } let it = idMaker(); console.log(it.next().value); // '0' console.log(it.next().value); // '1' console.log(it.next().value); // '2'
数据结构的默认Iterator接口 在ES6中,可迭代数据结构(比如数组)都必须实现一个名为Symbol.iterator的方法,该方法返回一个该结构元素的迭代器。注意,Symbol.iterator是一个Symbol,Symbol是ES6新加入的原始值类型。let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); console.log(iter); console.log(iter.next()); // { value: 'a', done: false } console.log(iter.next()); // { value: 'b', done: false } console.log(iter.next()); // { value: 'c', done: false } console.log(iter.next()); // { value: undefined, done: true }
上面代码中,变量arr是一个数组,原生就具有遍历器接口,部署在arr的Symbol.iterator属性上面。所以,调用这个属性,就得到遍历器。调用默认Iterator接口的场合
有一些场合会默认调用iterator接口(即Symbol.iterator方法),除了下文会介绍的for...of循环,还有几个别的场合。
解构赋值 对数组和Set结构进行解构赋值时,会默认调用iterator接口。
let set = new Set().add('a').add('b').add('c'); let [x,y] = set; // x='a'; y='b' let [first, ...rest] = set; console.log(first);//'a' console.log(rest);// ['b','c']; //扩展运算符 //扩展运算符(...)也会调用默认的iterator接口。 // 例一 let str = 'hello'; console.log([...str]); // ['h','e','l','l','o'] // 例二 let arr = ['b', 'c']; console.log(['a', ...arr, 'd']);// ['a', 'b', 'c', 'd']
其他场合 以下场合也会用到默认的iterator接口,可以查阅相关章节。yield*
Array.from()
Map(), Set(), WeakMap(), WeakSet()
Promise.all(), Promise.race()
原生具备Iterator接口的数据结构
字符串是一个类似数组的对象,也原生具有Iterator接口。
let someString = "hi"; typeof someString[Symbol.iterator]// "function" let iterator = someString[Symbol.iterator](); iterator.next() // { value: "h", done: false } iterator.next() // { value: "i", done: false } iterator.next() // { value: undefined, done: true } //上面代码中,调用Symbol.iterator方法返回一个遍历器,在这个遍历器上可以调用next方法,实现对于字符串的遍历。 //可以覆盖原生的Symbol.iterator方法,达到修改遍历器行为的目的。 let str = new String("hi"); [...str] // ["h", "i"] str[Symbol.iterator] = function() { return { next: function() { if (this._first) { this._first = false; return { value: "bye", done: false }; } else { return { done: true }; } }, _first: true }; }; [...str] // ["bye"] str // "hi" //上面代码中,字符串str的Symbol.iterator方法被修改了,所以扩展运算符(...)返回的值变成了bye,而字符串本身还是hi。
六、Iterator接口与Generator函数Symbol.iterator方法的最简单实现,还是使用下一章要介绍的Generator函数。