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()```javascriptlet 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)}
