前置:前后加了 % 代表着这是 ECMAScript 内部抽象化的语言表现形式。例如:我们看到的 Object.prototype 在语言内部抽象后所表现的就是 %ObjectPrototype%。其实所代表的就是 Object 的 原型方法。JS
Iterator遍历器
ES中,Array、Object、Map、Set是表示“集合”的数据结构。从抽象一些的角度来看,它们都是由多个元素/数据组合而成的。Iterator就是一种接口,为不同的数据结构提供同意的访问机制。ES6中,如果要使用for...of...
和 yield*
来访问变量,就必须要实现Iterator接口。
iterator接口内容
- next()方法(必选):返回值为IteratorResult对象
- return()方法(可选):返回一个done为true的IteratorResult,调用这个方法表示后续不能再进行next方法了
- throw()方法(可选):调用此方法表示遍历过程当中出现错误。
IteratorResult接口
属性 | 类型 | 描述 |
---|---|---|
done | true/false | done不存在默认为false,如果遍历到结束位置,为true |
value | 任意类型 | value值不一定会返回,done为false返回遍历到的当前元素,done为true返回this对象。 |
ES6文档中,提到所有实现了Iterator接口的对象,都继承了%IteratorPrototype% Object。我们就来看看这个对象包括什么。
遍历器原型对象(%IteratorPrototype% Object)
ES6规范中,提供了可以直接获取到%IteratorPrototype% Object的代码:
Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))
ecma262/#sec-%iteratorprototype%-object
我们可以看到,这个对象当中有个名为[Symbol.iterator]
的方法。该方法最后返回this。
既然每个实现Iterable都继承了这个原型对象,那么说明,实现Iterable对象的话也需要实现[Symbol.iterator]()
这个方法。
- 用ts代码表示Iterable接口可以表现如下
interface Iterable{
[Symbol.iterator]():Iterator
}
interface Iterator{
next(value?:any):IteratorResult
}
interface Iterator{
value:any,
done:boolean
}
es6.ruanyifeng.com/#docs/iterator
因此,我们可以看到如果一个数据结构具有Symbol.iterator属性,就可以认为是可遍历的。可以使用for…of去循环。
iterator遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置。
- 调用指针对象的next昂法,把指针指向数据结构的第一个成员。
- 继续调用next,指针指向下一个成员。直到当前的位置已经超出了数组的长度,说明已经到达结束位置了。
//实现一个iterator
//定义一个方法,传入一个对象,返回一个可枚举的对象,
//调用next方法会输出传入obj里面的key-value值
//(暂时认为对象取值只包含数字和字符串)
Input: var obj = {
'pos1':1,
'pos2':2
'pos3':3
}
Output:
{value:{'pos1':1},done,false},
{value:{'pos2':2},done,false},
{value:{'pos3':3},done,false},
什么时候调用Iterator接口
- 解构赋值
- 扩展运算符
- yield*
- for…of、Array.from、Map(),Set(),WeakMap(),WeakSet(),promise.all,promise.race