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()等等,可以发现,每个方法都有自己的规则,比如返回值什么的。

那么,我们可以通过迭代器,去自定义循环规则,通过迭代器,返回自己想要的结果。