for..of是ES6中引入的新特性,它主要的作用是:循环一个可迭代的对象。
它可以循环遍历,数组、字符串、Set对象等等,先来看两个简单的例子:
遍历字符串
let str = 'Hello'
for (item of str) {
console.log(item) // 会依次打印H e l l o
}
遍历数组
let arr = [1,2,3,4,5]
for(arrItem of arr){
console.log(arrItem) // 会依次打印 1 2 3 4 5
}
遍历对象
let obj = {
x:10,
y:20
}
for(objItem of obj){
console.log(objItem)
}
其实遍历对象的时候,会报一个错误:“Uncaught TypeError: obj is not iterable” ,大概意思就是obj对象是一个不可迭代的对象,或者说它没有迭代器。
怎么办呢?那就给obj添加一个迭代器。
迭代器
接着上面的例子,我们给obj添加一个迭代器
obj[Symbol.iterator] = ()=>{
}
紧接着,我们要在方法里面去写一下迭代规则,就是说,你想怎么去迭代这对象。这个方法需要返回一个next方法,next方法里面,又需要返回一个对象,
并且这个对象里面需要有"done"属性,“done”的值为bool类型的值,它相当于一个条件(或者说是开关),
判断是否需要继续循环,值为true时,跳出循环;值为false继续下一次循环;看个例子:
let obj = {
x:10,
y:20
}
obj[Symbol.iterator] = ()=> {
return {
next(){
return {
done: false,
value:2
}
}
}
}
for(objItem of obj){
console.log(objItem)
}
上面这个例子,第一次循环的时候,返回{done:false,value:2},打印“2”,第二次、第三次.... done的值一直是false,会出现死循环,一直打印“2”,
我们知道,如果要跳出循环,done的值要等于true,所以,我们可以加一些条件,当把对象遍历完毕之后,跳出循环:
let obj = {
x:10,
y:20
}
obj[Symbol.iterator] = ()=> {
let keys = Object.keys(obj) //获取对象的key值
let len = keys.length
let n = 0
return {
next(){
if (n<len){ //继续循环
return {
done: false,
value: obj[keys[n++]] // 每次循环返回的值
}
} else { // 跳出循环
return {
done: true
}
}
}
}
}
for(objItem of obj){
console.log(objItem) // 依次打印 10 20
}
总结:常见的循环方法有,for循环、map()、forEach()、filter()等等,可以发现,每个方法都有自己的规则,比如返回值什么的。
那么,我们可以通过迭代器,去自定义循环规则,通过迭代器,返回自己想要的结果。