Iterator可迭代接口

for..of..

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
}

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遍歷的對象都有

  • 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..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);
}

Generator

生成器函數以前講過

上面也使用生成器實現了iterable接口

案例:添加一個發號器

//發號器
function * creatId(){
  let id=1
  while(true){
    yield id++
  }
}
const g = creatId()
g.next()
g.next()
g.next()
相關文章
相關標籤/搜索