for...of循环

亡梦爱人 提交于 2020-04-06 06:45:53

for of 循环语句

for...of 循环语句

ES6为实现了迭代器接口的数据提供了统一访问访机制:新增了一个循环语句 — for...of循环语句;该语句会自动寻找Iterator接口。所以数据只要实现了Iterator接口,该数据就是可以被遍历的;该接口默认部署在Symbol.iterator属性上

原生的数据实现了迭代器接口的有:ArrayStringMapSetTypedArray(如 Int8Array),argumentsNodeList, HTMLCollection

   // 字符串迭代器接口
        console.log(String.prototype[Symbol.iterator])
        //类数组 迭代器
        let arr = new Int8Array(4)
        arr[0] = 10
        arr[1] = 100
        // arr[2] = 1000
        arr[2] = 2 ** 7 - 1
        console.log(arr)
        //参数
        function demo() {
        console.log(arguments)
        }
        demo()
        console.log(document.getElementsByTagName('div'));
        console.log(document.querySelectorAll('div'));

        // 遍历迭代器
        // for (let item of arr) {
        for (let item of document.getElementsByTagName('div')) {
            console.log(item)
        }

调用Iterator接口

  1. 数组的解构
   // =======数组 解构执行了
        let arr = [1,2,3];
        arr[Symbol.iterator]= function(){
            return {
                next() {
                console.log('iterator done')
                return { value: 'hello', done: true }
                }
            }    
        }
        let [a,b,c] = arr
        //对象解构 不会执行
        let obj = { num: 100 }
        // 重写迭代器接口
        obj[Symbol.iterator] = function() {
            return {
                next() {
                    console.log('iterator done')
                    return { value: 'hello', done: true }
                }
            }
        }
        let { num } = obj;
  1. 扩展运算符(三个点语法)
        //三点语法
        let arr = [1, 2, 3];
        // let arr = new Set([4, 5, 6])
        // let arr = new Map([[100, 200]])
        // 默认没有迭代器方法
        // let arr = new WeakSet([location])// 注意没有三个点语法
        // let arr = { num: 200 }
        // 重写迭代器接口
        arr[Symbol.iterator] = function() {
            return {
                next() {
                    console.log('iterator done!!!')
                    return { value: 'hello', done: true }
                }
            }
        }
        console.log([...arr])
  1. for...of循环
  2. Array.from方法
// 4 Array.from会执行参数对象的迭代器方法
// let divs = document.querySelectorAll('div');
// divs[Symbol.iterator] = function() {
//     return {
//         next() {
//             console.log('iterator done!!!')
//             return { value: 'hello', done: true }
//         }
//     }
// }
// console.log(Array.from(divs))
  1. MapSetWeakMapWeakSet参数
  // map和set实现了迭代器接口,而WeakSet和WeakMap没有实现
        console.log(Map.prototype[Symbol.iterator])
        console.log(Set.prototype[Symbol.iterator])
        console.log(WeakMap.prototype[Symbol.iterator])
        console.log(WeakSet.prototype[Symbol.iterator])// 5 set map, weakset, weakmap
        // let arr = [1, 2, 3];
        // let arr = [[100, 200], ['color', 'red'], [2, 3]];
        // let arr = [[location, 200]];
        // // 重写迭代器接口
        // arr[Symbol.iterator] = function() {
        //     return {
        //         next() {
        //             console.log('iterator done!!!')
        //             return { value: 'hello', done: true }
        //         }
        //     }
        // }
        // 创建set对象
        // console.log(new Set(arr));
        // console.log(new Map(arr));
        // console.log(new WeakSet(arr));
        // console.log(new WeakMap(arr));

  1. Promise.allPromise.race
// let divs
let arr = [1, 2, 3];
arr[Symbol.iterator] = function() {
    return {
        next() {
            console.log('iterator done!!!')
            return { value: 'hello', done: true }
        }
    }
}
Promise.all(arr)
Promise.race(arr)
  1. 字符串对象解构
// 7 字符串对象解构
let str = new String('111')
str[Symbol.iterator] = function() {
    return {
        next() {
            console.log('iterator done!!!')
            return { value: 'hello', done: true }
        }
    }
}
console.log([...str])
  1. generator函数的yield语句等

returnthrow

迭代器接口返回的对象中,除了必须定义next方法外,还可以设置returnthrow方法:

  • return方法:当for...of语句提前结束的时候会使用该方法。 如在for...of语句中使用了break或者continue关键字
  • throw方法主要配合generator函数使用。
// ========= return 
let arr = [1,2,3,4,5,6,7,8]
arr[Symbol.iterator] = function(){
    //缓存tis
    let me = this;
    return {
        index:1,
        next(){
            this.index++;
            if(this.index===me.length){
                return {value:undefined,done:true}
            }
            return {value:me[this.index],done:false}
        },
        //终止方法
        return(){
            console.log("121212")
            return {value:me[this.index],done:true}
        }
    }
}
//遍历
// for(let item of arr){
//     if(item===3){
//         break
//     }
// }
ickt:for(let i = 0;i<3;i++){
    for(let item of arr){
        console.log(item)
        if(item===3){
            continue ickt;
        }
    }
}

for...of 循环 注意事项

  1. 遍历数组
    1. 只能遍历数字索引属性,不能遍历其它属性
    let arr = [4,5,6,7,8]
    // 添加书香
    arr.color = "red"
    //遍历
    for(let item of arr){
        console.log(item,"121")
    }
    
    1. for循环只能获取成员值,无法获取索引值(for...in正好相反),可以借用keys以及entries解决
    // ==== for of 注意事项
    let arr = [4,5,6,7,8]
    // 添加书香
    arr.color = "red"
    //遍历
    for(let item of arr){
        console.log(item,"121")
    }
    // keys values entries
    for(let item of arr.keys()){
        console.log(item)
    }
    for(let item of arr.values()){
        console.log(item)
    }
    for(let item of arr.entries()){
        console.log(item)
    }
    
  2. setmap对象
    1. 遍历的顺序就是成员添加的顺序
    2. set返回的是成员值,map返回的是包含索引值与成员值的数组。
  3. keysvalues以及entries是专门为迭代器接口设计的方法,因此for...of循环可以遍历这些方法返回的数据
let set = new Set();
set
    .add('color')
    .add('red')
    .add('green')
for (let item of set) {
    console.log(item)//// 返回键值
}
// 没有键名,只有键值
for (let item of set.entries()) {
    console.log(item)// 返回键值对
}

let map1 = new Map()
map1
    .set('color', 'red')
    .set('num', 100)
    .set('green', 'blue')
  for (let item of map1) {
    console.log(item) // 返回键值对
}  
console.log(Set.prototype[Symbol.iterator] === Set.prototype.values)
console.log(Map.prototype[Symbol.iterator] === Map.prototype.entries)

  1. for...of循环还可以遍历字符串,类数组对象(实现了迭代器接口的)。
// 遍历类数组和字符串
let str = 'ickt';
for (let item of str) {
    console.log(item)
}
// 遍历类数组
function demo() {
    for (let item of arguments) {
        console.log(item)
    }
}
demo(1, 2, 3, 4, 5)

对于未实现迭代器接口的类数组对象可以使用Array.from方法转化

// 没有实现迭代器接口
let arrLike = {
    0: 'red',
    1: 'green',
    2: 'blue',
    length: 3
}
// 没有实现迭代器接口的对象,无法遍历,为了遍历可以使用Array.from方法转化。
for (let item of Array.from(arrLike)) {
    console.log(item)
}
  1. for...of循环可以遍历实现迭代器接口的对象。没有实现迭代器接口的对象我们可以使用Object.keysvaluesentries等方法转化,也可以使用generator方法处理
// 对象
let obj = {
    color: 'red',
    msg: 'hello',
    num: 100
}
// for (let item of obj) {
//     console.log(item)
// }
// 转成数组
// for (let item of Object.keys(obj)) {
//     console.log(item)
// }
// for (let item of Object.values(obj)) {
//     console.log(item)
// }
// for (let item of Object.entries(obj)) {
//     console.log(item)
// }
// generator
// function *demo() {
//     yield 1;
//     yield 2;
//     yield 3;
// }
// 将属性键值对定义成状态
function *demo(obj) {
    // 遍历对象属性名称
    for (let key in obj) {
        yield [key, obj[key]]
    }
}
let d = demo(obj);
// console.log(d.next())
// console.log(d.next())
// console.log(d.next())
// console.log(d.next())
for (let item of d) {
    console.log(item)
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!