高下相倾,前后相随——iterator 与 for ... of 循环

时间:2022-09-02 20:49:30

  iterator 是es6新提供的一种遍历器。本质上是一个接口,为各种不同的数据结构,提供统一的访问机制。

  数据只要部署了iterator接口,便是可遍历的数据,标志是具有Symbol.iterator属性。换句话说,我们只要给数据部署这个属性,就可以将数据变为可遍历的数据。具体表现是数据能否用for...of 遍历。

  原生具有iterator接口的数据类型:set, map, nodeList,string, arguments。这些数据类型是可以用for...of 遍历的。 

// 数组的Symbol.iterator
let arr = [1,2,4,65];
let iter = arr[Symbol.iterator]();
console.log(iter.next())
// 一个对象如果要具备可被for of 循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成的方法
class RangeIterator {
constructor(start, stop){
this.value = start;
this.stop = stop;
}
[Symbol.iterator](){return this}
next () {
let value = this.value;
if (value < this.stop) {
this.value ++ ;
return {done: false, value: value}
} else {
return {done: true, value: undefined}
}
}
}
function range(start, stop) {
return new RangeIterator(start, stop)
}
for (let v of range(0, 3)) {
// console.log(v)
} // 遍历器实现指针结构的例子
function obj(value) {
this.value = value;
this.next = null;
}
obj.prototype[Symbol.iterator] = function () {
let iterator = {next: next};
let current = this;
function next() {
if (current) {
let value = current.value;
current = current.next;
return {done: false, value: value};
} else {
return {done: true}
}
}
return iterator;
}
let one = new obj(1);
let two = new obj(2);
let three = new obj(3);
one.text = two;
two.next = three;
for (let i of one) {
console.log(i)
}
// 对于类数组的对象(存在键值名和length属性),部署iterator接口,有一个简单的方法,就是Symbol.iterator 方法直接引用数组的Iterator接口
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 或者
NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
// 默认调用iterator的场合
/*
* 解构赋值
* 扩展运算符
* yield*
* 数组的遍历会调用遍历器的接口,所以任何接受数组为参数的场合,都会调用遍历器接口
*
* */
// 字符串的iterator 接口
let str = 'adf';
let str_iterator = str[Symbol.iterator]();
console.log(str_iterator.next(), str_iterator.next(), str_iterator.next())