• 迭代器和for-of


    在ES5及之前的JS标准中,我们习惯了用for(var i = 0; i < Array.length;i++){//TODO}或者是for(var index in Array){console.log(Array[index]);}或forEach

    前者固然是好的,而后两个毛病多多,forEach不能够用return或者break中断循环,index in Array 返回的index不是数字,而是字符串“0”,“1”,“2”等等,因此衍生了功能强大的for-of


    for-of

    for( var value of Array){

      console.log(value);

    }

    避开了所有for-in的缺陷。for-in循环用来遍历对象属性,for-of循环用来遍历数据——如数组中的值。

    for-of循环支持一切类数组对象,如DOM NodeList对象。

    for-of也支持字符串遍历,它将字符串看做一系列的Unicode字符来进行遍历:

    for( var chr of “”){

      console.log(chr);

    }

    也支持Map和Set的对象遍历(这两个类型是ES6新增,如果你在别的语言中用过,与ES6中的差别不大)。

    for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用for-in循环(这也是它的本职工作)或内建的Object.keys()方法:

    // 向控制台输出对象的可枚举属性
    for (var key of Object.keys(someObject)) {
    console.log(key + ": " + someObject[key]);
    }正如其它语言中的for/foreach语句一样,for-of循环语句通过方法调用来遍历各种集合。数组、Maps对象、Sets对象以及其它在我们讨论的对象有一个共同点,它们都有一个迭代器方法。

    你可以给任意类型的对象添加迭代器方法。

    当你为对象添加myObject.toString()方法后,就可以将对象转化为字符串,同样地,当你向任意对象添加myObject[Symbol.iterator]()方法,就可以遍历这个对象了。

    举个例子,假设你正在使用jQuery,尽管你非常钟情于里面的.each()方法,但你还是想让jQuery对象也支持for-of循环,你可以这样做:


    // 因为jQuery对象与数组相似
    // 可以为其添加与数组一致的迭代器方法
    jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];


    这里通过Symbol处理了一下方法的名称。标准委员会可以把这个方法命名为.iterator()方法,但是如果你的代码中的对象可能也有一些.iterator()方法,这一定会让你感到非常困惑。于是在ES6标准中使用symbol来作为方法名,而不是使用字符串。

    现在,你需要记住,基于新标准,你可以定义一个全新的 symbol,就像Symbol.iterator,如此一来可以保证不与任何已有代码产生冲突。这样做的代价是,这段代码的语法看起来会略显生硬,但是 这微乎其微代价却可以为你带来如此多的新特性和新功能,并且你所做的这一切可以完美地向后兼容。

    所有拥有[Symbol.iterator]()的对象被称为可迭代的。在接下来的文章中你会发现,可迭代对象的概念几乎贯穿于整门语言之中,不仅是for-of循环,还有Map和Set构造函数、解构赋值,以及新的展开操作符。

    迭代器对象


    var zeroesForeverIterator = {
    [Symbol.iterator]: function () {
    return this;
    },
    next: function () {
    return {done: false, value: 0};
    }
    };

    每一次调用.next()方法,它都返回相同的结果,返回给for-of循环的结果有两种可能:(a) 我们尚未完成迭代;(b) 下一个值为0。这意味着(value of zeroesForeverIterator) {}将会是一个无限循环。当然,一般来说迭代器不会如此简单。
    迭代器对象也可以实现可选的.return()和.throw(exc)方法。如果for-of循环过早退出会调用.return()方法,异常、 break语句或return语句均可触发过早退出。如果迭代器需要执行一些清洁或释放资源的操作,可以在.return()方法中实现。大多数迭代器方 法无须实现这一方法。.throw(exc)方法的使用场景就更特殊了:for-of循环永远不会调用它。但是我们还是会在下一篇文章更详细地讲解它的作 用。

    现在我们已了解所有细节,可以写一个简单的for-of循环然后按照下面的方法调用重写被迭代的对象。


    for (VAR of ITERABLE) {
    一些语句
    }

    var $iterator = ITERABLE[Symbol.iterator]();
    var $result = $iterator.next();
    while (!$result.done) {
    VAR = $result.value;
    一些语句
    $result = $iterator.next();
    }
    这段代码没有展示.return()方法是如何处理的,我们可以添加这部分代码,但我认为这对于我们正在讲解的内容来说过于复杂了。for-of循环用起来很简单,但是其背后有着非常复杂的机制。

  • 相关阅读:
    C# 函数式编程
    【python】 入门 搭建环境
    luogu P3978 [TJOI2015]概率论
    luogu P4778 Counting swaps
    luogu P2480 [SDOI2010]古代猪文
    luogu P3243 [HNOI2015]菜肴制作
    luogu P4744 [Wind Festival]Iron Man
    luogu P4448 [AHOI2018初中组]球球的排列
    luogu P1593 因子和
    luogu P1943 LocalMaxima_NOI导刊2009提高(1)
  • 原文地址:https://www.cnblogs.com/zzy528/p/4865624.html
Copyright © 2020-2023  润新知