• for..of的用法


    先来简单说说for…of与for…in的区别

    for…in 遍历数组 -> 下标; 遍历对象 -> 键

    for…of 遍历数组 -> 值; 遍历对象 -> 无法遍历普通对象

    一般情况下,for…of不能去遍历普通对象

    原因是: 普通对象没有 Symbol.iterator 属性,如果一个对象拥有 Symbol.iterator 属性,那么就可以使用for … of 遍历了

    // 若是想要 for...of 遍历对象,那我们就手动添加 Symbol.iterator 属性
    let obj = {
        data: ['hello', 'one'],
        [Symbol.iterator]() {
            const self = this;
            let index = 0;
            return {
                next() {
                    if(index < self.data.length) {
                        return {
                            value: self.data[index++],
                            done: false
                        };
                    }else {
                        return {
                            value: undefined,
                            done: true
                        }
                    }
                }
            }
        }
    }
    for(let value of obj) {
        console.log(value);  // world  one
    }
    // 类似数组的对象遍历  直接引用 Array.prototype[Symbol.iterator]
    // 普通对象部署数组的Symbol.iterator方法,并无效果
    let iterator = {
        0: 'a',
        1: 'b',
        2: 'c',
        length: 3,
        [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for(let item of iterator) {
        console.log(item);  // 'a', 'b', 'c'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    当为对象添加 obj.toString() 方法后,就可以将对象转化为字符串,同样的,向任意对象添加 obj[Symbol.iterator]() 方法,就可以遍历这个 对象了。这个对象也被称为 可迭代的

    可通过 Symbol.iterator 方法确定某个数据是否可迭代:

    const array = [1, 2, 3];
    const iterator = array[Symbol.iterator]();
    iterator.next();  // { value: 1, done: false }
    
    • 1
    • 2
    • 3

    for … of 接收可迭代对象,可以遍历 String 、数组、类数组、set、map,包括上面的对象

    迭代器对象

    for...of 最常见的应用是对数组进行迭代,可以高效地完成迭代,而且无需其他变量来保持索引。

    简单了解以下迭代器

    迭代器对象是可以拥有任意具有 .next() 方法的对象,for…of 循环将重复调用这个方法,每次循环将重复调用这个方法,每次循环调用一次。

    以下是一个简单的迭代器:

    let iterator - {
        [SYmbol.iterator]: function() {
            return this;
        },
        next: function() {
            return {
                done: false,
                value: 0
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    每调用一次 .next() 方法,它都返回相同的结果,返回给for…of循环的结果有两个可能:

    • 尚未完成,done: false
    • value为0

    这意味着 这个迭代器(iterator) 将会是一个无限循环,当然,平常时用到的迭代器不会这么简单。

    迭代器对象也可以实现可选的 .return().throw(exc) 方法。如果for…of循环过早退出会调用 .return() 方法,而异常、break语句 或 return语句均可触发过早退出;

    如果迭代器需要执行一些清洁或释放资源的操作,可以在 .return() 方法中实现,大多数迭代器方法无须实现这一方法;

    .throw(exc) 方法的使用场景:for…of循环永远不会调用它(这里就不扯远了)

    接下来就可以,可以写一个简单的 for…of循环调用重写被迭代的对象:

    // for...of 循环
    for (let k of iterable) {
        // 一些语句
    }
    
    • 1
    • 2
    • 3
    • 4
    // 然后使用以下方法和变量实现与之前大致相当的功能
    let $iterator = iterable[Symbol.iterator]();
    let $result = $iterator.next();
    while (!$result.done) {
        let value = $result.value;
        // 操作
        $reslut = $iterator.next();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里没有 .return() 方法,我们可以自己添加上这部分代码,但是这样就扯远了。for…of循环用起来很简单,但是背后的机制略有点复杂

  • 相关阅读:
    unity项目加密(比如到指定时间,项目打不开)
    自定义类型(结构体、位段、联合体、枚举)
    如何设计一个牛逼的消息队列?
    【面试题】给你一个项目,你准备怎么开展ui自动化
    【C++笔试强训计划】第一天
    macbook电脑磁盘满了怎么删东西?
    【英语:基础高阶_学术写作训练】J1.写作的基本逻辑
    磁盘原理简要分析
    数据库用户管理
    智慧燃气巡检管理系统
  • 原文地址:https://blog.csdn.net/weixin_45663702/article/details/126137933