Iterator迭代器 【ES6】
学无止境
目录
- Iterator是什么?
- Iterator作用:
- 遍历过程:
- 深入剖析:
- 哪些数据结构自带 Symbol.iterator?
- 为什么普通对象不能 for...of?
- 让对象变成可迭代的:
- 结论:
- 简单构造迭代器的方法:
Iterator是什么?
在前端开发中,迭代器(Iterator) 是一种用于遍历数据集合的接口。迭代器提供了一种统一的方式来访问集合中的元素,而无需暴露集合的内部结构。
Iterator作用:
引言:需要遍历的每个值 数组可以通过for循环-索引值找到;对象可以通过for-in找到;那么Set呢?Map呢?要通过什么方式能找到? 由于数据结构太多,所以:
- 为各种数据结构提供一个统一的、简便的访问接口
- 是的数据结构的成员能够按某种次序排列
- for…of循环(ES6新创的遍历命令;Iterator主要用for…of循环)
遍历过程:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员
- 第二次调用指针对象的next方法,指针指向数据结构的第二个成员
- 不断调用只针对想的next方法,直到它指向数据结构的结束位置
const array = [1, 2, 3, 4, 5];
// 获取数组的迭代器
const iterator = array[Symbol.iterator]();
// 使用迭代器遍历数组
let result = iterator.next();
while (!result.done) {console.log(result.value);result = iterator.next();
}
结果如下:
深入剖析:
哪些数据结构自带 Symbol.iterator?
ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性(一个数据结构只要有Symbol.iterator属性,就可以认为是可遍历的)
数据类型 | 是否可迭代 | 示例 |
---|---|---|
Array | ✅ 有 | [1,2,3][Symbol.iterator]() |
String | ✅ 有 | "abc"[Symbol.iterator]() |
Map | ✅ 有 | new Map()[Symbol.iterator]() |
Set | ✅ 有 | new Set()[Symbol.iterator]() |
TypedArray(如 Int8Array) | ✅ 有 | new Int8Array()[Symbol.iterator]() |
Arguments(类数组对象 Array-like Object) | ✅ 有 | function fn(){ arguments[Symbol.iterator]() } |
DOM NodeList(节点集合,类数组) | ✅ 有 | document.querySelectorAll('div')[Symbol.iterator]() |
Object(普通对象) | ❌ 默认没有 | {a:1}[Symbol.iterator] // undefined |
为什么普通对象不能 for…of?
因为它 没有实现 Symbol.iterator。【对象是非线性的】
const obj = { a: 1, b: 2 };for (const x of obj) { // ❌ TypeError: obj is not iterableconsole.log(x);
}console.log(obj[Symbol.iterator]); // undefined
让对象变成可迭代的:
加一个 Symbol.iterator 方法:
const obj = {a: 1,b: 2,[Symbol.iterator]() {const entries = Object.entries(this)let index = 0return {next() {if (index < entries.length) {return { value: entries[index++], done: false }} else {return { done: true }}}}}
}for (const [k, v] of obj) {console.log(k, v); // a 1 / b 2
}
let obj = {code:200,name:'obj',list:['a','b','c'],[Symbol.iterator](){let index = 0;return {next:()=>{if(index<this.list.length){return {done:false,value:this.list[index++]}}else{return {done:true,value:null}}}}}
}for(let item of obj){console.log(item); // a <br/> b <br/> c
}
结论:
只要一个对象拥有 obj[Symbol.iterator]()
方法,它就是一个“可迭代对象”,可以被 for...of
、… 等语法使用。
简单构造迭代器的方法:
function getIterator(list) {let i = 0;return {next: function () {let done = (i >= list.length);let value = done ? undefined : list[i++];return {value: value,done: done};}};
}
const arr = getIterator(['a', 'b', 'c']);
console.log(arr.next());// {value: "a", done: false}
console.log(arr.next());// {value: "b", done: false}
console.log(arr.next());// {value: "c", done: false}
console.log(arr.next());// "{ value: undefined, done: true }"