JavaScript迭代协议

308 阅读5分钟

迭代协议具体分为两个协议:可迭代协议 和 迭代器协议。

可迭代协议

1. 可迭代协议是什么?

允许 JavaScript 对象定义或定制它们自己的迭代行为的协议,称之为可迭代协议。

对于实现了可迭代协议的对象我们称之为可迭代对象。

2. 如何判断某个对象为可迭代对象?

符合以下两点的对象即为可迭代对象:

  • 对象必须有一个名为 @@iterator的属性,可通过常量 Symbol.iterator 访问该属性。
  • 该属性会返回一个符合迭代器协议的对象的无参数函数。

String对象是一个可迭代对象。以String对象为例进行验证。

迭代协议

  • 第一条语句验证了字符串对象确实存在@@iterator 的属性,且返回值为一个函数;

  • 第二条语句至第四条语句验证了这个函数是一个返回了符合迭代器协议对象的无参数函数。(对于迭代器协议不了解的同学先不要纠结,下文会讲到)

3. 实现了可迭代协议的JS内置对象都有哪些?

除了上述提到的String对象,还有ArrayTypedArrayMap 和Set等四个JS内置对象实现了可迭代协议。

4. 将可迭代对象作为参数,实现类型转换

很多内置 API 接受可迭代对象(可迭代对象写作:iterable,下同)作为参数,例如 迭代协议 举例如下: 迭代协议

第二,三条语句中,创建Set对象的传入的参数分别是数组和字符串,比较好理解。那创建Map对象时传入的可迭代对象,我们应该如何构造得来呢? Object对象有一个方法叫做entries(),entries()方法会返回一个给定对象自身可枚举属性的键值对数组,说白了就是上面创建Map对象时传入的可迭代对象。代码验证: 迭代协议

第一二步验证了Object.entries()方法会返回和上述创建Map对象时传入的参数相同的数据结构 第三到第五步证明了Object.entries()方法返回的对象是一个可迭代对象。

至此,我们已经掌握了数组、字符串转化为Set,对象转换为Map的方式。另外,接受可迭代对象作为参数的内置 API还有: 迭代协议

5. 实现自己的可迭代对象

实现自己的可迭代对象,重写可迭代行为 具体实现参考MDN。

6. 用于可迭代对象的语法

一些语句适用于可迭代对象,比如 for...of 循环、展开语法、yield*和解构赋值。 迭代协议

迭代器协议

1. 迭代器协议是什么?

定义了产生一系列值(无论是有限个还是无限个)的标准方式的协议,我们称之为迭代器协议。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。 实现了迭代器协议的对象我们称之为迭代器对象。

2. 迭代器对象特征

迭代器对象拥有以下两点特征:

  • 对象必须实现了一个拥有next() 方法,且next() 方法是一个无参方法。
  • next() 方法返回一个拥有以下两个属性的对象:done(boolean)和value。 迭代协议

3. 迭代器对象示例

简单迭代器代码示例如下: 迭代协议

伪数组

最后,为了使 “对象类型转换网” 更丰富更全面,我打算把伪数组对象也“织”进去,因此这里再介绍一下伪数组。

1. 什么是伪数组?

伪数组,又称类数组。伪数组的原型是对象(Object)。之所以称之为伪数组,是因为和数组有相同的地方:

  • 有length属性
  • 可以通过索引访问元素

2.与数组区别是什么?

不存在数组的方法:如 pop,push等数组方法。

3.常见的类数组有哪些?

  • 函数的参数列表 argument对象。
  • DOM 对象列表(比如通过 document.querySelectorAll 得到的列表)。
  • jQuery 对象。 
  • input的文件对象FileList。

4. 类数组转化为数组的方式有哪些?

  • 使用call()方法。写法:Array.prototype.slice.call(arrayLike, start);
  • ES6的展开语法。 写法:[...arrayLike];
  • 数组对象内置的from方法。 写法:Array.from(arrayLike);

5.如何判断某个对象是否为类数组对象?

《javascript权威指南》上给出了代码用来判断一个对象是否属于“类数组”。如下: 迭代协议

6.类数组和可迭代对象的联系与区别

可迭代对象与类数组对象本质上是两个完全不同的概念,下面介绍其区别与联系。

联系:

  • 可以使用 Array.from将可迭代对象和类数组对象转为真实数组。
  • 一些对象可能既是伪数组又是可迭代对象。例如:函数参数列表arguments对象。

区别:

  • 可迭代对象 是指实现了 [Symbol.iterator]方法属性的对象。
  • 类数组对象 具有一个 .length属性的对象。

对象转换关系图

1.对象转换关系图

迭代协议

2. 举例说明对象之间的转换

简单举例说明利用迭代协议进行对象转换的代码

  • Object对象转Map 对象 迭代协议

  • Mep对象转Set对象 迭代协议

  • String、Array和Set的相互转换 迭代协议

这只是一部对象转换关系,当熟悉迭代协议以后你可以进行更灵活的对象转换。

3.for…of的使用

for...of循环语法是ES6提供的语法,这个方法是可迭代对象专属的循环方法,因此对于可迭代对象都可以用for…of完成。Object虽然不是迭代器对象,但是我们可以对object类型的对象进行可迭代对象的转换(Object.entries()),便可以使用for…of语法。 for…of是名副其实的宝藏语法。

如果错误欢迎指正,转载请注明出处。