ES6 (9):iterator 遍历器

摘要:
遍历器就是这样一种机制。ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值。ArrayMapSetStringTypedArray函数的arguments对象NodeList对象对于原生部署Iterator接口的数据结构,不用自己写遍历器生成函数,for...of循环会自动遍历它们。使用while循环遍历:var$iterator=ITERABLE[Symbol.iterator]();var$result=$iterator.next();while(!

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

作用:

一是为各种数据结构,提供一个统一的、简便的访问接口;

二是使得数据结构的成员能够按某种次序排列;

三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

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

阮大神的模拟代码:(makeIterator 内部形成了一个闭包)

var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

其中done:false 和 value:undefined 可以省略。

当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口

ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为 Symbol 的特殊值。

const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

原生具备 Iterator 接口的数据结构如下。

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象

对于原生部署 Iterator 接口的数据结构,不用自己写遍历器生成函数,for...of循环会自动遍历它们。除此之外,其他数据结构(主要是对象)的 Iterator 接口,都需要自己在Symbol.iterator属性上面部署,这样才会被for...of循环遍历

let obj = {
  data: [ 'hello', 'world' ],
  [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 };
        }
      }
    };
  }
};

类似数组的对象调用数组的Symbol.iterator方法的例子。

let iterable = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
  console.log(item); // 'a', 'b', 'c'
}

如果Symbol.iterator方法对应的不是遍历器生成函数(即会返回一个遍历器对象),解释引擎将会报错。

使用while循环遍历:

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
  var x = $result.value;
  // ...
  $result = $iterator.next();
}

调用iterator 接口的场合:

1.解构赋值

2.扩展运算符

3.yield*

4.其他场合

  • for...of
  • Array.from()
  • Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]])
  • Promise.all()
  • Promise.race()

字符串具有iterator 接口。

ES6 (9):iterator 遍历器第1张

覆盖原生的Symbol.iterator方法:

var str = new String("hi");

[...str] // ["h", "i"]

str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};

[...str] // ["bye"]
str // "hi"

遍历器对象的returen、throw:遍历器对象除了具有next方法,还可以具有return方法和throw方法。如果你自己写遍历器对象生成函数,那么next方法是必须部署的,return方法和throw方法是否部署是可选的。

当使用循环遍历器时使用了break 或者抛出错误时,都会触发执行return 方法。

function readLinesSync(file) {
  return {
    [Symbol.iterator]() {
      return {
        next() {
          return { done: false };
        },
        return() {
          file.close();
          return { done: true };
        }
      };
    },
  };
}

for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。这一点跟for...in循环也不一样。

let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) {
  console.log(i); //  "3", "5", "7"
}

不会返回数组arr的foo属性。

类似数组的对象

for...of循环用于字符串、DOM NodeList 对象、arguments对象

对于字符串来说,for...of循环还有一个特点,就是会正确识别 32 位 UTF-16 字符

并不是所有类似数组的对象都具有 Iterator 接口,一个简便的解决方法,就是使用Array.from方法将其转为数组(在数组的地方说了,还有Array.of是针对一个序列)。

let arrayLike = { length: 2, 0: 'a', 1: 'b' };

// 报错
for (let x of arrayLike) {
  console.log(x);
}

// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

对于数组的forEach循环,无法中途跳出forEach循环,break命令或return命令都不能奏效

ES6 (9):iterator 遍历器第2张

for...in循环有几个缺点:

  • 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
  • for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键
  • ES6 (9):iterator 遍历器第3张

    修改为类似数组的对象,使用for...of 循环

  • ES6 (9):iterator 遍历器第4张
  • 某些情况下,for...in循环会以任意顺序遍历键名

for...of循环相比上面几种做法,有一些显著的优点:

  • 有着同for...in一样的简洁语法,但是没有for...in那些缺点。
  • 不同于forEach方法,它可以与breakcontinuereturn配合使用
  • 提供了遍历所有数据结构的统一操作接口。

ES6 (9):iterator 遍历器第5张

免责声明:文章转载自《ES6 (9):iterator 遍历器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇一不注意,在Unity3D中DllImport 引起的Bug.PostgreSQL内存占用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

java基础知识--日期时间类

1.1 Date类  java.util.Date类 表示特定的瞬间,精确到毫秒。 继续查阅Date类的描述,发现Date拥有多个构造函数,只是部分已经过时,但是其中有未过时的构造函数可以把毫秒值转成日期对象。 public Date():分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。 public Date(long date)...

如何正确使用Java泛型

前言 Java 1.5之前是没有泛型的,以前从集合中读取每个对象都必须先进行转换,如果不小心存入集合中对象类型是错的,运行过程中转换处理会报错。有了泛型之后编译器会自动帮助转换,使程序更加安全,但是要正确使用泛型才能取得事半功倍的效果。 本文主要从不要使用原生类型,泛型方法,限制通配符,类型安全的异构容器四个部分来说明如何正确使用Java泛型。主要参考资...

【JavaScript数据结构系列】02-栈Stack

【JavaScript数据结构系列】02-栈Stack码路工人 CoderMonkey转载请注明作者与出处 ## 1. 认识栈结构 栈是非常常用的一种数据结构,与数组同属线性数据结构,不同于数组的是它是一种受限的线性结构。 画一张图来说明: 如上图所示, 最新入栈的元素/最底下的元素,为栈底 最后一个/最上面的元素,为栈顶 最后一个入栈元素最先出栈(L...

数据结构-王道-图

目录 图的基本概念 有向图 简单图 多重图 完全图 子图 连通,连通图和连通分量 邻接表法 十字链表 十字链表 BFS算法求解单源最短路径问题 深度优先搜索(Depth-First-Search) 图的应用 最小生成树(Minimum-Spaning-Tree) Prime算法 KruSkal算法 最短路径 Dijkstra算法 Floy...

js 过滤数组里对象的某个属性

需求 一个大数组,里面乱七八糟一堆属性。现在只需要其中两个属性,用这两个属性组成一个对象,重新得到一个新数组。新数组长度跟老数组一样,只不过里面所有对象只剩下了两个属性 示例 handleSelectionChange(selection) { var invoiceGxQueryList = []; for (var i =...

es6 Interator

概念:interator(遍历器)是一种接口机制,为一种具有遍历结构的或者有length长度的数据结构提供一种统一的访问机制,从而进行遍历操作 作用: 1.为各种数据结构,提供一个统一的,简便的访问接口 2.使得数据结构的成员按某种次序排列 3.es6 提供了一种新的遍历for of循环,interator主要为for of使用 原理: 1.创建一个指针对...