使用for of遍历可迭代数据时,会调用其[Symbol.Iterator]方法。
目前有[Symbol.iterator]方法的数据类型有:
- 字符串 String
- 数组 Array
- 映射 Map
- 集合 Set
- arguments对象
- Nodelist等DOM集合
Number与Object实例无[Symbol.iterator]方法,如果要使用for of遍历对象,便需要重写其[Symbol.iterator]方法
第一步:重写Object实例的[Symbol.iterator]方法
- 使用next函数
- 可以根据需要遍历,本次以遍历value为例
- 遍历对象的值,使用:Object.values(obj),本案例使用该方法
- 遍历对象的键,使用:Object.keys(obj)
- 遍历对象的键/值,使用:Object.entries(obj) ```javascript let obj = {name:’zhangsan’,age:18,habby:’basketball’}
// 重写[Symbol.iterator]方法 obj[Symbol.iterator] = function(){ let index = 0 // 返回next函数 return { // next函数需要返回两个参数:每次迭代返回的值value,迭代是否结束的标志done next(){ let values = Object.values(obj) // 取出对象的所有值,写在next方法中可以避免在迭代过程中obj发生变化 if (index < values.length){ return { done:false, // 遍历还未结束 value:values[index++] // index++先运算,再加1 } }else{ return { done:true // 遍历结束 } } }, // 在for of中提前中止迭代,会自动调用这个return方法(比如break,continue,throw等) return(){ console.log(‘Exiting early’) return {done:true} } } }
<a name="UVuzm"></a>
### 第二步,使用for of遍历对象
```javascript
for (let k of obj){
console.log(k) // zhangsan 18 basketball
}
/*---------*/
for (let k of obj){
if (k==18){
continue
}
console.log(k) //zhangsan basketball Exiting early
}
/*---------*/
for (let k of obj){
if (k==18){
break
}
console.log(k) //zhangsan Exiting early
}
拓展
- 重写后的[Symbol.iterator]其实就是一个生成器
- 生成器中本身就具有next,return,throw方法
- 以下写法未解决,在调用next方法的过程中,对象发生变化的情况 ```javascript let obj = {name:’zhangsan’,age:18,habby:’basketball’}
// 重写[Symbol.iterator]方法,function加上号表示生成器函数 obj[Symbol.iterator] = function(){ let values = Object.values(obj) // yield加上表示挨个取出里面的元素 yield values } ```
补充:
可迭代对象,可以使用以下方法:
- for-of 循环
- 数组解构
- 扩展操作符
- Array.from()
- 创建集合
- 创建映射
- Promise.all()接收由期约组成的可迭代对象
- Promise.race()接收由期约组成的可迭代对象
- yield*操作符,在生成器中使用