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'
}

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

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

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

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

迭代器对象

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

简单了解以下迭代器

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

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

let iterator - {
    [SYmbol.iterator]: function() {
        return this;
    },
    next: function() {
        return {
            done: false,
            value: 0
        }
    }
}

每调用一次 .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) {
    // 一些语句
}
// 然后使用以下方法和变量实现与之前大致相当的功能
let $iterator = iterable[Symbol.iterator]();
let $result = $iterator.next();
while (!$result.done) {
    let value = $result.value;
    // 操作
    $reslut = $iterator.next();
}

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@乐知者@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值