array, array-like, iterable

array, array-like, iterable

先看一个关于array-like和iterable的定义:

Iterables and array-likes:

There are two official terms that look similar, but are very different. Please make sure you understand them well to avoid the confusion.

  • Iterables are objects that implement the Symbol.iterator method, as described above.
  • Array-likes are objects that have indexes and length, so they look like arrays.

因为数组实例的原型链上实现了 Symbol.iterator 接口,所以数组是iterable对象:

对可迭代对象(iterable)可以使用扩展运算符 ... 以及 for..of 循环:

var arr = [1, 2, 3, 4];
var arr2 = [...arr];

console.log(arr2);	// 1,2,3,4,5

for (let value of arr) {
  console.log(value);	// 1 2 3 4 5	  -- 带换行
}

而类数组(array-like)不一定实现了 Symbole.iterator 方法,如果不是iterable对象,是无法使用[...arrlike] 扩展成数组的,也不能使用 for..of 做迭代,比如:

var arrlike = {
  0: 100,
  1: 200,
  2: 300,
  length: 3
};

var arr = [...arrlike];		// SyntaxError: Unexpected token

for (let value of arrlike) {	// TypeError: arrlike is not iterable
  console.log(value);
}

有一个简便方法可以将iterable或array-like转换为数组,这个方法是 Array.form(),其语法如下:

Array.from(obj[, mapFn[, thisArg]])	// 形参是巴科斯范式BNF 表示法
// 参数含义可自行查询 MDN文档

用法如下:

var arrlike = {
  0: 100,
  1: 200,
  2: 300,
  length: 3
};

var arr = Array.from(arrlike);

console.log(arr);	// 100,200,300

对应 iterable 还可以使用 扩展运算符来转换成数组 [...iterable]:

var iterable = {
  *[Symbol.iterator] () {
  	for (let i = 1; i <= 4; i ++) {
 			yield i;
  	}
  }
}

var arr = [...iterable];
console.log(arr);	// 1,2,3,4

在之前也看到了,对array-like 且 non-iterable的对象使用 [...arrlike] 会报错。

所以,不能使用扩展运算符将单纯的array-like转换为数组!

补充

在ECMAScript2018之后对任意对象可以使用扩展运算符:

var obj = {
  a: 100,
  b: 200,
  c: 300
};

var obj2 = {...obj};
console.log(obj2);	// {a: 100, b: 200, c: 300}

// 但是这样只能将对象转换为对象,依旧不能将 non-iterable 对象转换为数组
var arr = [...obj];	

// 注意区别 {...obj} 与 [...iterable]
posted @ 2019-09-21 21:36  Wenksti  阅读(430)  评论(0编辑  收藏  举报