3/4 关于JavaScript迭代器

写在前面

  仅供自用

  ...


Iterable 接口

  在我的理解里面,如果数据结构实现了 Iterable 接口 那么 这个数据结构就是可迭代对象

  当然实现这个的方法 就是 写一个迭代器工厂函数 [Symbol.iterator] 来生成一个含有 next(){}  和 return(){} 两个属性方法的对象 也就是 迭代器

Iterator 迭代器

  next()

  迭代器 进行对 可迭代对象的消费 ( 我的理解就是 通过 next() 来一步一步把 可迭代对象 ( 实现 Iterable 接口的 数据结构 ) 榨干 )

let arr_3 = [1,2,3];
let iter = arr_3[Symbol.iterator](); // 记得加一个() 立即执行函数 得到返回的一个 迭代器 iterator 
console.log(iter); // 可以验证一下 得到  Array Iterator {}
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: undefined, done: true} 表示读完了 done为true的嘛

  return()

  return() 是当遇到了 break continue 或者是 throw 提前结束 迭代器 操作的 属性

class Test {
    // 构造函数
    constructor(limit){
        this.limit = limit;
    }
    // 通过闭包 实现 Iteratable 接口 [Symbol.iterator] 函数就是一个 迭代器工厂 返回一个迭代器对象 里面有 next() 和 return() 方法
    [Symbol.iterator](){
        let limit = this.limit;
        let start = 0;
        // 返回 一个对象 其中有属性next() ( 我们必须实现这个方法才是实现了 Iterable 接口)
        return{
            // 不断调用 next() 实现迭代
            next(){
                if(start < limit){
                    return {done:false,value:start++}; // 下次增加 第一次为 0 扩展为 0 1 2 3
                    // return {done:false,value:++start}; // 本次增加 第一次为 1 如果扩展则为 1 2 3 4
                }
                else{
                    return {done:true,value:undefined};
                }
            },
            // 当遇到 break continue throw 提前退出 调用的属性方法 应当返回一个 {done:true}
            return(){
                console.log("提前结束");
                return { done:true };
            }
        }
    }
}

// 实例化 一个 test
let test1 = new Test(4);
// 扩展运算符测试 是否正常 
console.log(...test1); // 0 1 2 3 
// 通过 for-of 测试 提前结束
for (const iterator of test1) {
    if(iterator === 2){
        break;
    }
    console.log(iterator);
} // 0 1 提前结束

  当然 有一些可迭代对象 没办法重启 (一般来说叫关闭)迭代器状态 比如数组

  这个时候return形如虚设...( 这个是针对可迭代对象的迭代器而言,可迭代对象无法直接对符号 [Symbol.iterator] 进行更改 )

console.group(4);
let arr_4 = [0,1,2,3,4];
let iteratorOfArr4 = arr_4[Symbol.iterator]();

// 开始重新覆盖 迭代器的 return(){}
iteratorOfArr4.return = function(){
    console.log("提前结束");
    return {done:true};
}
console.log(iteratorOfArr4); // 可以看到 加入了 return(){}

// 因为 iteratorOfArr4 相当于实现了 iterable 接口 而且关联了一个可迭代对象 arr_4 所以自己也是一个可迭代对象
// 但是这里 ta 自己不能 控制关闭迭代器状态
for (const iterator of iteratorOfArr4) {
    console.log(iterator);
    if(iterator == 2){
        break;
    }
} // 0 1 2 提前结束
for (const iterator of iteratorOfArr4) {
    console.log(iterator); 
} // 3 4

// 如果 for-of 用于 arr_4 但是原有的迭代器没有被重新覆盖 只是 iteratorOfArr4 写了
console.log(arr_4[Symbol.iterator]());  // Array Iterator {}
arr_4[Symbol.iterator]().return = function(){
    console.log("提前结束");
    return {done:true};
}
console.log(arr_4[Symbol.iterator]());  // 可以看到加不进去 因为是 符号 没法改变( 猜想 ) 只能通过 在期望 可迭代对象的地方 用ta自己的迭代器来实现某些操作

for (const iterator of arr_4) {
    console.log(iterator);
    if(iterator == 2){
        break;
    }
} // 0 1 2 
for (const iterator of arr_4) {
    console.log(iterator); 
} // 0 1 2 3 4
Let it roll
原文地址:https://www.cnblogs.com/WaterMealone/p/14488061.html