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