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..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 循环时一种数据对立遍历的形式
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 可迭代接口须要满足
- 有 [Symbol.iterator] 办法
- [Symbol.iterator] 办法返回一个对象,这个对象实现了迭代器接口 Iterator
- 返回的对象具备一个 next 办法,
- next 办法返回一个 IterationResult 迭代后果的对象
- 对象有两个参数 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()