一、Object(四种集合):无序
- 遍历自身及原型?
for in
:遍历自身及继承
的可枚举属性
。但es6规定,所有 Class 的原型的方法都是不可枚举的- 总结:不适合遍历。(会遍历原型)
- 遍历自身所有、symbol属性、可枚举:
三种集合
- 遍历
自身所有属性(除symbol)
:Object.getOwnPropertyNames(obj)- 遍历
自身symbol属性
:getOwnPropertySymbols(obj)- 遍历
自身可枚举属性
:assign、entries、keys、values
遍历顺序
- Chrome 浏览器:
先数字,其它的按创建顺序排序
- 其它浏览器:按照创建顺序排序
- 总结:
对象的遍历是无序的
二、Array(一种原始,五种Es5迭代):
- 原始:
for(let i=0;i<length;i++){}
- Es5迭代(语义化,简洁)
every
测试所有,返回布尔值some
测试部分,返回布尔值filter
过滤,返回新数组map
映射,返回新数组forEach
迭代,修改自身
Es5迭代机制
:内部完成for迭代,用户传处理函数即可
因此:我们在处理函数,使用break或者return,是没办法终止迭代的 !!!
- 但我们可以利用some、every的机制来终止(个人不建议,语义会歧义)
说明
:虽然Array继承于Object,但Object的迭代不适合Array
三、ES6新增的迭代器Iterator(提供统一接口
)
一、
Iterator迭代器
:
- 类似es5的迭代。两层函数。
- 由之前的自动迭代=>函数调用迭代(
可控
)const obj = { randomName() { let index=0; return { next(){ index+=1; if(index<3) return {value: 0,done: false} else return {value:1,done:true} } }; } }; const obj2=obj.randomName();//启动迭代器,下面可控迭代 console.log(obj2.next());//{ value: 0, done: false } console.log(obj2.next());//{ value: 0, done: false } console.log(obj2.next());//{ value: 1, done: true }
二、
迭代工具for of
:是Iterator迭代器的迭代工具机制(对比手动使用Iterator,自动化执行了以下
4
个步骤)
- 默认会查找
[Symbol.iterator]
的函数,作为迭代器- 启动迭代器
- 执行迭代
- 处理返回来的结果
- done作为是否继续迭代的条件(done:true时,终止迭代,及不再执行for of主体)
- value作为结果
const obj = { [Symbol.iterator]() { let index=0; return { next(){ index+=1; if(index<3) return {value: 0,done: false} else return {value:1,done:true} } }; } }; for(item of obj){ console.log(item);//0 0 即value作为结果。done:true时,终止迭代,及不再执行for of主体 } console.log("手动调用",obj[Symbol.iterator]().next());//手动调用 { value: 0, done: false }
- 三、
预设了[Symbol.iterator]迭代器的对象有:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
总结
:即对数组、类数组、String预设了迭代器
- 四、
会默认调用[Symbol.iterator]迭代器的场景有:
- 解构赋值:
先对右边装包
,再迭代器
,再匹配给左边
- 拓展运算符:
先迭代器
,再转化
为需要的格式:如[...obj]即转化为数组,{...obj}即转化为对象
补充:
object默认是没有提供迭代器的,但解构赋值或者拓展的时候,会先转化为Map再处理
- generator生成器
- 其它;Array.from(),Promise.all(),Promise.race()等
四、 generator生成器
和迭代器的关系
- 迭代器是
迭代属性
的- 生产者,是
生成迭代器
的一个函数:迭代的是被field分割的代码块