共计 4017 个字符,预计需要花费 11 分钟才能阅读完成。
目录
-
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 iterable
let 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)
}
// 吃饭
// 睡觉
// 打豆豆
// 语文
// 数学
// 外语
// 喝茶
ES6-ES10 学习幅员
正文完