Iterator
迭代器是一个特殊的对象,有 next方法,每次返回
{value:xx, done:false/true}
的对象
Iterator 的作用有三个:
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列
- ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供 for…of 消费。
每一次调用 next 方法,返回一个包含 value 和 done 两个属性的对象。其中,value 属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}
默认Iterator接口
ES6 规定,默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,或者说,一个数据结构只要具有Symbol.iterator 属性,就可以认为是“可遍历的”(iterable)。
Symbol.iterator 属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名 Symbol.iterator,它是一个表达式,返回 Symbol 对象的 iterator 属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内:
// 对象obj是可遍历的
const obj = {
[Symbol.iterator] : function () {
return {
next: function () {
return {
value: 1,
done: true
};
}
};
}a
};
原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- 函数的 arguments 对象
- NodeList 对象
- TypedArraya ```javascript let arr = [‘a’, ‘b’, ‘c’]; let iter = arrSymbol.iterator;
iter.next() // { value: ‘a’, done: false } iter.next() // { value: ‘b’, done: false } iter.next() // { value: ‘c’, done: false } iter.next() // { value: undefined, done: true }
有一些场景会默认调用 Iterator 接口:
- 解构赋值
- 扩展运算符
- yield* 后面跟的是一个可遍历的结构
- 其他:
- for...of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如`new Map([['a',1],['b',2]])`)
- Promise.all()
- Promise.race()
```javascript
let myIterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
[...myIterable] // [1, 2, 3]
遍历方法对比
普通for
- 只能遍历数组, 不能遍历对象
forEach
- 无法遍历对象
- 不能提前结束循环
- 对元素进行判断可以使用:
every()
some()
find()
findIndex()
- forEach会跳过空元素 如[1,,2]
for-of
- 可中断循环
- 不能遍历对象
for-in
- for in 可用于遍历数组和对象, 输出的是数组的索引和对象的key,
- 一般用于遍历对象,迭代非Symbol类型的可枚举属性
先遍历出整数属性(integer properties,按照升序),然后其他属性按照创建时候的顺序遍历出来。
break | continue | return | 性能(ms) | |
---|---|---|---|---|
for | 终止 ✔️ | 跳出本次循环✔️ | 终止循环✔️ | 2.42 |
forEach | ❌ ️报错 | ❌报错 | 跳出当前的循环 | 3.12 |
for-of | ✔️ | ✔️ | ✔️ | 6.33 |
for-in | ✔️ | ✔️ | 跳出当前的 循环 |
遍历对象
- for-in
- Object.keys()、Object.value()、Object.entries()
- Object.getOwnPropertyNames() :所有的可枚举的属性值,不包括 Symbol
- Object.getOwnPropertySymbols() : 所有 Symbol 属性名,包括不可枚举
- Reflect.ownKeys() : 包含对象自身的所有属性,包括Symbol,包括不可枚举
let obj = {name:"abc", age:24, job:"程序员"};
for(let key in obj){
console.log(key); //name,age,job
}
for (const key of Object.keys(obj)) {
console.log(key, obj[key])
}
for (const value of Object.values(obj)) {
console.log(value)
}
for (const [key, value] of Object.entries(obj)) {
console.log(key, value)
}