美文网首页
Iterator 和 for...of 循环

Iterator 和 for...of 循环

作者: 弱冠而不立 | 来源:发表于2020-11-14 18:02 被阅读0次

    阮一峰文档连接

    Iterator (遍历器是什么)

    JS 中可迭代的数据结构主要是 array,object,map和set。用户可以组合使用它们,定义自己的数据结构,例如数组成员是Map,而Map成员是对象,所以就需要一种统一的接口机制,来处理不同类型的数据结构。
    遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

    Iterator 的遍历过程

    1. 创建一个指针对象,指向当前数据结构的起始位置,即,遍历器本质上就是一个指针对象
    2. 第一次调用指针对象的 next 方法,可以将指针指向数据结构的第一个成员
    3. 不断调用指针对象的 next 方法,直到它指向数据结构的结束位置

    每一次调用 next 方法都会返回数据结构的当前成员信息,具体来说,就是返回一个包含 value 和 done 两个属性的对象。其中,value 属性是当前成员的值,done 属性是一个布尔值,表示遍历是否结束

    默认 Iterator 接口

    Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for...of循环(详见下文)。当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口。
    一种数据类型,只要部署了 Iterator 接口,我们就称这种数据结构是"可遍历的"。

    ES6 规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,即,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”。原生具备 Iterator 接口的数据结构如下。
    Array
    Map
    Set
    String
    TypedArray //ES7新增,描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视(view)
    函数的 arguments 对象
    NodeList 对象

    let arr = ['a', 'b', 'c'];
    let iter = arr[Symbol.iterator]();
    
    iter.next() // { value: 'a', done: false }
    iter.next() // { value: 'b', done: false }
    iter.next() // { value: 'c', done: false }
    iter.next() // { value: undefined, done: true }
    

    调用 Iterator 接口的场合

    有一些场合会默认调用 Iterator 接口(即Symbol.iterator方法),除了下文会介绍的for...of循环,还有几个别的场合。

    1. 解构赋值
      对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法。
    let [x, y, z] = new Set([1, 2, 3])
    
    1. 扩展运算符
      扩展运算符(...)也会调用默认的 Iterator 接口。
    [..."hello"]
    

    也就是说,只要某个数据结构部署了 Iterator 接口,就可以对它使用扩展运算符,将其转为数组。

    Iterator 接口与 Generator 函数

    Symbol.iterator()方法的最简单实现就是结合 Genenrator 函数

    let myIterable = {
            [Symbol.iterator]: function* () {
                yield 1;
                yield 3;
                yield 5;
            }
        }
        console.log([...myIterable]); // [1, 3, 5]
    

    for...of 循环与其他遍历语法的比较

    JavaScript 原有的for...in循环,只能获得对象的键名,不能直接获取键值。ES6 提供for...of循环,允许遍历获得键值。

    var arr = ['a', 'b', 'c', 'd'];
    for (let a in arr) {
      console.log(a); // 0 1 2 3
    }
    for (let a of arr) {
      console.log(a); // a b c d
    }
    

    例如:

    1. forEach,中途跳出forEach循环,break命令或return命令都不能奏效。
    2. for...in循环可以遍历数组的键名。for...in循环有几个缺点。
      数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
      for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
      某些情况下,for...in循环会以任意顺序遍历键名。

    for...of循环相比上面几种做法,有一些显著的优点
    有着同for...in一样的简洁语法,但是没有for...in那些缺点。
    不同于forEach方法,它可以与break、continue和return配合使用。
    提供了遍历所有数据结构的统一操作接口。

    相关文章

      网友评论

          本文标题:Iterator 和 for...of 循环

          本文链接:https://www.haomeiwen.com/subject/dqgvbktx.html