Iterator接口的目的是:为所有的数据结构提供一种统一的访问机制,即for。。。of 循环。
当使用for。。。of 循环遍历某种数据结构时,该循环会自动寻找Iterator接口。
一种数据结构只要部署了Iterator接口,我们就称这种数据结构是可遍历的
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是“可遍历的”(iterable)。
Symbol.iterator
属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。
原生具备Iterator接口的数据结构如下:
Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象
eg:
let arr = [1,2,3]
let iter = arr[Symbol.Iterator]()
iter.next() // { value: '1', done: false }
iter.next() // { value: '2', done: false }
iter.next() // { value: '3', done: false }
iter.next() // { value: undefined, done: true }
在上面的例子中,arr是一个数组,原生就有Itarator遍历器接口。部署在arr的Symbol.Iterator属性上面,所以调用这个属性就能得到遍历器对象。
除了for...of
循环会默认调用Iterator接口外,还有其他场合:
1.对数组和Set数据结构进行解构赋值或使用扩展运算符时,会默认调用Symbol.iterator
方法。
解构赋值
let [x,y] = set;
使用扩展运算符
只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符,将其转为数组。
// 例一
var str = 'hello';
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
yield*
yield*
后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
let generator = function* () {
yield 1;
yield* [2,3,4];
yield 5;
};
var iterator = generator();
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }