JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
——《ECMAScript 6 入门:Iterator和for…of循环》(阮一峰)
迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费。
工作原理
调用iterator接口时,返回一个iterator对象,调用该iterator对象的next方法。
每次调用next方法时返回可遍历对象的当前成员。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function iterateFunc(array) { var nextIdx = 0; return { next() { return nextIdx < array.length ? { value: array[nextIdx++], done: false } : { done: true }; } }; } var it = iterateFunc(['a','b', 'c']); for (var x in it) { console.log(x); }
|
调用迭代器的场合
1 2 3 4 5 6 7 8 9 10 11 12
| String.prototype[Symbol.iterator] = function(){ var index = 0; return { next:() => { return index < this.length ? { value: this[this.length -1 - index++], done: false } : { done: true }; } }; }; NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
|
- 为对象编写自定义迭代器
iterator本质上是线性操作,但是对象的遍历顺序是非线形的,所以ES6没有为对象内置原生的[Symbol.iterator]()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var obj = { a: 1, b: 2, c: 3, [Symbol.iterator]: function () { var self = this; var keys = Object.keys(self); var index = 0; return { next: function () { return index < keys.length ? { value: self[keys[index++]], done: false } : { done: true } } } } }
|
上述实现方式其实比较繁琐,利用Object.keys(obj).forEach(key => obj[key])
其实效率更高
参考