目录
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新增)
迭代器协定 —— 怎么个迭代形式?返回无参函数next
,next
返回一个对象蕴含done
和value
属性
PS: 这个构造是不是和Generator
特地像?如果
next
函数返回一个非对象值(比方false
和undefined
) 会展现一个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)}// 吃饭// 睡觉// 打豆豆// 语文// 数学// 外语// 喝茶