for-of 遍历对象
/ / 点击 / 阅读耗时 5 分钟Iterator 接口
Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for…of循环。当使用for…of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口。一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”(iterable)。
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回 Symbol 对象的 iterator 属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内。
对象进行for…of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器:
1、添加 next 方法:
1 | const obj = { |
2、Generator:
1 | class Collection { |
由于Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的Symbol.iterator属性,从而使得该对象具有Iterator接口。
1 | var myIterable = {} |
下面是原生具备Iterator接口的数据结构:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
也就是数组和类数组才有Symbol.iterator属性,而 Object 是没有的。
那么怎么做到使对象可遍历?
方法一:部署 Iterator 接口(在 Symbol.iterator 的属性上部署遍历器生成方法)
一个对象如果要具备可被for…of循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
1 | class RangeIterator { |
方法二:使用 Object.keys
1 | for (var key of Object.keys(someObject)) { |
方法三:使用 Generator 函数将对象重新包装
1 | function* entries(obj) { |