手撕Iterator遍历器

123 阅读1分钟

概念

遍历器(Iterator)是一种机制(接口):为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作,依次处理该数据结构的所有成员

  • 拥有next方法用于依次遍历数据结构的成员
  • 每一次遍历返回的结果是一个对象 {done:false,value:xxx}
    • done:记录是否遍历完成
    • value:当前遍历的结果
  • 拥有Symbol.iterator属性的数据结构(值),被称为可被遍历的,可以基于for of循环处理
    1. 数组
    2. 部分类数组:arguments/NodeList/HTMLCollection...
    3. String
    4. Set
    5. Map
    6. generator object
  • 对象默认不具备Symbol.iterator,属于不可被遍历的数据结构
let arr = [10, 20, 30, 40];
for (let item of arr) {
    // for of内部是按照 iterator.next 去迭代处理,所以只有具备 Symbol.iterator 
    //属性「也就是具备Iterator迭代规范的」,才可以基于for of遍历 
    console.log(item);
}

代码实现和测试

代码实现

class Iterator {
    constructor(assemble) {
        // 挂载到实例的私有属性上:方便后期在方法中基于实例获取这些值
        // assemble:数字作为索引逐级递增、拥有length属性存储集合长度
        let self = this;
        self.assemble = assemble;
        self.index = 0;
    }
    next() {
        let self = this,
            assemble = self.assemble,
            index = self.index;
        if (index > assemble.length - 1) {
            // 遍历结束了
            return {
                done: true,
                value: undefined
            };
        }
        return {
            done: false,
            value: assemble[self.index++]
        };
    }
}

代码测试

let itor = new Iterator([10, 20, 30, 40]);
console.log(itor.next()); //->{done:false,value:10}
console.log(itor.next()); //->{done:false,value:20}
console.log(itor.next()); //->{done:false,value:30}
console.log(itor.next()); //->{done:false,value:40}
console.log(itor.next()); //->{done:true,value:undefined}

相关题目

let obj = {
    0: 10,
    1: 20,
    2: 30,
    3: 40,
    length: 4,
    // [Symbol.iterator]: Array.prototype[Symbol.iterator]
    /* [Symbol.iterator]: function () {
        return new Iterator(this);
    } */
    [Symbol.iterator]: function () {
        let self = this,
            index = 1;
        return {
            next() {
                if (index > self.length - 1) {
                    return {
                        done: true,
                        value: undefined
                    };
                }
                let result = {
                    done: false,
                    value: self[index]
                };
                index += 2;
                return result;
            }
        };
    }
};
for (let item of obj) {
    console.log(item);
}