目录

  • ES6如何让不反对遍历的构造可遍历?

    • 将所有的作者名称取出来
    • for-of须要Object.entries进行转化
  • 规定

    • 可迭代协定 —— 去找对象下面有没有Symbol.iterator属性
    • 迭代器协定 —— 怎么个迭代形式?返回无参函数next,next返回一个对象蕴含done和value属性
  • Generator 和 lterator 联合应用
  • 案例
  • ES6-ES10学习幅员

ES6如何让不反对遍历的构造可遍历?

let authors = {  allAuthors: {    fiction: [      'Agatha Christie',      'J. K. Rowling',      'Dr. Seuss'    ],    scienceFiction: [      'Neal Stephenson',      'Arthur Clarke',      'Isaac Asimov',      'Robert Heinlein'    ],    fantasy: [      'J. R. R. Tolkien',      'J. K. Rowling',      'Terry Pratchett'    ]  }}

将所有的作者名称取出来

ES5的做法

allAuthors进行遍历,看看取值状况

for(let [k,v] of Object.entries(authors.allAuthors)){  console.log(k,v)}//fiction (3) ["Agatha Christie", "J. K. Rowling", "Dr. Seuss"]//scienceFiction (4) ["Neal Stephenson", "Arthur Clarke", "Isaac Asimov", "Robert Heinlein"]// fantasy (3) ["J. R. R. Tolkien", "J. K. Rowling", "Terry Pratchett"]// 所以正确的写法是:let r = []for(let [k,v] of Object.entries(authors.allAuthors)){  r = r.concat(v)}console.log(r)//["Agatha Christie", "J. K. Rowling", "Dr. Seuss", "Neal Stephenson", "Arthur Clarke", "Isaac Asimov", "Robert Heinlein", "J. R. R. Tolkien", "J. K. Rowling", "Terry Pratchett"]

每次都须要遍历,而且还要对obj不反对遍历的对象进行革新。
而且还须要晓得authors的内部结构。

咱们的指标是:

  • 写法优雅
  • 数据结构种的内置逻辑不须要关怀
let r = []for(let v of authors){    console.log(v)    r.push(v)}

所以ES6的写法

//固定写法authors[Symbol.iterator] = function () {  // 输出 this,对象自身  let allAuthors = this.allAuthors  let keys = Reflect.ownKeys(allAuthors)  console.log(keys) // ["fiction", "scienceFiction", "fantasy"]  let values = [] // 是key的值  return {    // 必须返回一个办法    next () {      console.log(values)      //一开始values.length是0,如果是0就进入循环过程      if (!values.length) {        if (keys.length) {           values = allAuthors[keys[0]]          keys.shift() //永远取第一个元素,用完之后进行弹出        }      }      // 必须返回两个值      return {        done: !values.length,        value: values.shift()      }    }  }}let r = []for(let v of authors){  r.push(v)}console.log(r)//["Agatha Christie", "J. K. Rowling", "Dr. Seuss", "Neal Stephenson", "Arthur Clarke", "Isaac Asimov", "Robert Heinlein", "J. R. R. Tolkien", "J. K. Rowling", "Terry Pratchett"]

for-of须要Object.entries进行转化

let obj = {    1: "hello",    "a":"hi"};for(let i of obj){console.log(i,obj[i]);}//报错:Uncaught TypeError: obj is not iterablelet obj1 = Object.entries(obj);console.log(obj1) //[Array(2), Array(2)]for(let [k,v] of obj1){    console.log(k,v)}//1 hello//a hi

规定

可迭代协定 —— 去找对象下面有没有Symbol.iterator属性

  • 可迭代协定容许 JavaScript 对象去定义或定制它们的迭代行为, 例如(定义)在一个 for…of 构造中什么值能够被循环(失去)。一些内置类型都是内置的可迭代类型并且有默认的迭代行为, 比方 Array or Map, 另一些类型则不是 (比方Object) 。
  • 为了变成可迭代对象, 一个对象必须实现 @@iterator 办法, 意思是这个对象(或者它原型链 prototype chain 上的某个对象)必须有一个名字是 Symbol.iterator 的属性
  • 这里参考 遍历 —— for-of(ES6新增)

迭代器协定 —— 怎么个迭代形式?返回无参函数nextnext返回一个对象蕴含donevalue属性

PS: 这个构造是不是和Generator特地像?

如果 next 函数返回一个非对象值(比方falseundefined) 会展现一个 TypeError (“iterator.next() returned a non-object value”) 的谬误

//固定写法authors[Symbol.iterator] = function () {  // 输出 this,对象自身  // 输入 返回值(格局要求)  return {    // 必须返回一个next办法    next () {      // 必须返回两个值      return {        done: false, // boolean false-遍历没有完结 true-遍历完结        value: 1 // 以后遍历的我的项目的值      }    }  }}

Generator 和 lterator 联合应用

想理解Generator,参考文章 ES6(十四)—— Generator

//可迭代协定 加*就是Generator了authors[Symbol.iterator] = function * () {  // 输出 this,对象自身  let allAuthors = this.allAuthors  let keys = Reflect.ownKeys(allAuthors)  console.log(keys) // ["fiction", "scienceFiction", "fantasy"]  let values = [] // 是key的值  // 无线循环,如果退出之后,会主动停止退出的  while(1){    if(!values.length){      if(keys.length){        values = allAuthors[keys[0]]        keys.shift()        yield values.shift()      }else{        // 退出循环        return false      }    }else{      yield values.shift()    }  }}

案例

  • 场景:你我协同开发一个工作清单利用
  • 迭代器的意义: 内部不必去关怀外部的构造,间接进行遍历就能够拿到全副数据。
// each办法,是todos外部裸露的办法// 更好的是把todos间接变成一个可迭代的对象const todos = {  life: ['吃饭', '睡觉', '打豆豆'],  learn: ['语文', '数学', '外语'],  work: ['喝茶'],  each: function (callback) {    const all = [].concat(this.life, this.learn, this.work)    for( const item of all) {      callback(item)    }  },  [Symbol.iterator]: function() {    const all = [...this.life, ...this.learn, ...this.work]    let index = 0    return {      next: function () {        return {          value: all[index],          done: index++ >= all.length        }      }    }  }}todos.each(function(item){  console.log(item)})// 吃饭// 睡觉// 打豆豆// 语文// 数学// 外语// 喝茶for(const item of todos){  console.log("for-of: " +item)}

应用Generator函数实现Iterator办法,对下面的案例进行改良

const todos = {  life: ['吃饭', '睡觉', '打豆豆'],  learn: ['语文', '数学', '外语'],  work: ['喝茶'],  each: function (callback) {    const all = [].concat(this.life, this.learn, this.work)    for( const item of all) {      callback(item)    }  },  [Symbol.iterator]: function * () {    const all = [...this.life, ...this.learn, ...this.work]    for(const item of all) {      yield item    }  }}for(const item of todos){  console.log(item)}// 吃饭// 睡觉// 打豆豆// 语文// 数学// 外语// 喝茶

ES6-ES10学习幅员