for...of... 做为遍历全部数据结构的统一方式数组
for遍历普通数组数据结构
for in 遍历键值对dom
forEach 数组的遍历方法函数
const arr = [100,200,300,400] for(const item of arr){ console.log(item); //拿到的是每个元素,而不是对应的下标 if(item>300){ break; } } //取代forEach方法,for..of..能够使用关键词break随时终止,forEach没法终止遍历 arr.forEach(function(item,index){ })
其余的遍历工具
//伪数组的遍历(arguments) // dom操做时一些元素节点的列表 的遍历 //Set ,Map对象 const s = new Set(['foo',"bar"]) for(var i of s) { console.log(i); //foo bar }
配合结构使用测试
const m = new Map() m.set({a:1},"value") m.set(true,100) for(var mm of m){ console.log(mm); //[ { a: 1 }, 'value' ] [ true, 100 ] } //经过解构优化上面的for..of for(var [key,value] of m){ console.log(key,value); //{ a: 1 } value || true 100 }
注意,遍历对象会报错优化
//遍历对象会报错 const ddd = {naz:"mcgee",baz:100} for(var item of ddd){ console.log(item); //TypeError: ddd is not iterable }
for..of循环时一种数据统一遍历的方式this
for...of... Object TypeError 为何?spa
Es可以表示有结构的数据类型愈来愈多 array obj set map 组合形式code
Iterable怎么理解,就是一种接口(规格标准),例如任意一种数据类型都有toString方法,由于他们实现了统一的规格标准(实现了统一的接口)
可迭代接口就是一种 能够被for..of..循环遍历访问的规格标准
换句话说,若是他实现了可迭代接口,他就能被for of循环遍历
什么是可迭代
console.log([]) console.log(new Set()) console.log(new Map())
咱们发现能够被for -- of遍历的对象都有
const result = ["foo","bar","baz"] const iterator = result[Symbol.iterator]() console.log(iterator.next()) //{value: "foo", done: false} console.log(iterator.next()) //{value: "bar", done: false} console.log(iterator.next()) //{value: "baz", done: false} console.log(iterator.next()) //{value: undefined, done: true}
const s = new Set([1,2,"as","foo"]) const it2 = s[Symbol.iterator]() console.log(it2.next()) console.log(it2.next()) console.log(it2.next()) console.log(it2.next()) console.log(it2.next())
自定义一个iterable可迭代的接口
实现iterable可迭代接口须要知足
//对象实现一个iterable接口,对数组进行for..of const _iterable = [1,23,4] const ob = { [Symbol.iterator](){ let index=0 //计数器,用于判断是否迭代完成 return { next:function(){ return { value:_iterable[index], done:index++>=_iterable.length } } } } } for(var item of ob){ console.log(item) }
因为generator生成器也实现了iterator接口,所以上面方法能够进行改写
const ob = { * [Symbol.iterator](){ //简写:[Symbol.iterator]:function * (){} for(let item of _iterable) { yield item } } } for(var item of ob){ console.log(item) //1,23,4 }
案例
//我想获取一个文件下的数据 const obj = { work:["吃饭","睡觉","打豆豆"], learn:["and","fuck","your"], gos:["mother"], //经过回调方式 cb(callback){ const result = [].concat(this.work,this.learn,this.gos) for(var item of result){ callback(item) } }, //实现iterator接口,外部经过for..of..方式 [Symbol.iterator]:function (){ const arr = [...this.work,...this.learn,this.gos] let index=0; return { next:function(){ return { value:arr[index], done:index++>=arr.length } } } } }
傻瓜方式...
//耦合度过高,若是obj更改,则我还要加个方法 for(const item of obj.work) { console.log(item); } for(const item of obj.learn) { console.log(item); }
传统回调方式
//传统作法注册个回调 obj.cb(function(item){ console.log(item); })
for..of方式
//用可实现迭代接口 for(var item of obj){ console.log(item); }
生成器函数以前讲过
上面也使用生成器实现了iterable接口
案例:添加一个发号器
//发号器 function * creatId(){ let id=1 while(true){ yield id++ } } const g = creatId() g.next() g.next() g.next()