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]