for..of..

for...of... 作为遍历所有数据结构的对立形式

for遍历一般数组

for in 遍历键值对

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..offor(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}

Iterable 可迭代接口

for..of循环时一种数据对立遍历的形式

for...of... Object TypeError 为什么?

Es可能示意有构造的数据类型越来越多 array obj set map 组合模式

Iterable怎么了解,就是一种接口(规格规范),例如任意一种数据类型都有toString办法,因为他们实现了对立的规格规范(实现了对立的接口)

可迭代接口就是一种 能够被for..of..循环遍历拜访的规格规范

换句话说,如果他实现了可迭代接口,他就能被for of循环遍历

什么是可迭代

  • 控制台测试 帮忙->切换开发人员工具 查看输入后果
console.log([])console.log(new Set())console.log(new Map())


咱们发现能够被for -- of遍历的对象都有

  • proto -> Symbol(Symbol.iterator):f values()
  • iterator接口约定对象外部必须要挂载一个叫iterator的办法,这个办法返回一个带有next()办法的对象
  • 一直调用next,就能够实现对外部的遍历
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可迭代接口须要满足

  1. 有[Symbol.iterator] 办法
  2. [Symbol.iterator] 办法返回一个对象,这个对象实现了迭代器接口 Iterator
  3. 返回的对象具备一个next 办法,
  4. next办法返回一个 IterationResult 迭代后果的对象
  5. 对象有两个参数 value是每次的值,done示意是否实现迭代
//对象实现一个iterable接口,对数组进行for..ofconst _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);}

Generator

生成器函数之前讲过

下面也应用生成器实现了iterable接口

案例:增加一个发号器

//发号器function * creatId(){  let id=1  while(true){    yield id++  }}const g = creatId()g.next()g.next()g.next()