将ES6可迭代对象转换为数组

183

假设你有一个类数组的Javascript ES6 Iterable,你预先知道它将是有限长度的,那么将其转换为Javascript Array的最佳方法是什么?

这样做的原因是许多js库(如underscore和lodash)仅支持数组,因此如果您希望在Iterable上使用它们的任何功能,则必须首先将其转换为数组。

在Python中,你只需使用list()函数。ES6中是否有相应的函数?


43
Array.from(iterable),参见 ECMA-262 ed 6 draft - RobG
6个回答

267
您可以使用 Array.from展开语法 (...)
示例:

const x = new Set([ 1, 2, 3, 4 ]);

const y = Array.from(x);
console.log(y); // = [ 1, 2, 3, 4 ]

const z = [ ...x ];
console.log(z); // = [ 1, 2, 3, 4 ]


4
对于ES6 let m = new Map()数据结构,几乎同样适用:要获取Map的值,请使用Array.from或扩展运算符m.values(),对于m.keys()也是一样。否则,你将得到一个数组的数组:[[key, value], [key, value]] - Nik Sumeiko

27

摘要:

  • Array.from() 函数,它接受一个可迭代对象作为输入,并返回该可迭代对象的数组。
  • 扩展语法:使用数组字面量和 ... 运算符组合使用。

const map = new Map([[ 1, 'one' ],[ 2, 'two' ]]);

const newArr1  = [ ...map  ];  // create an Array literal and use the spread syntax on it
const newArr2 = Array.from( map );  // 

console.log(newArr1, newArr2); 

复制数组时的注意事项:

需要知道的是,当我们想要复制一个数组时,上述方法仅会创建一个浅拷贝。以下示例将说明可能存在的问题:

let arr = [1, 2, ['a', 'b']];

let newArr = [ ...arr ];

console.log(newArr);

arr[2][0] = 'change';

console.log(newArr);

由于嵌套数组的存在,引用被复制而不是创建新的数组。因此,如果我们改变旧数组中内部数组的值,这个变化将会反映在新数组中(因为它们引用同一个数组,引用已被复制)。

解决方法:

我们可以通过使用 JSON.parse(JSON.stringify(array)) 来创建数组的深拷贝以解决浅拷贝的问题。例如:

let arr = [1, 2, ['a', 'b']]

let newArr = Array.from(arr);

let deepCloneArr = JSON.parse(JSON.stringify(arr));

arr[2][0] = 'change';

console.log(newArr, deepCloneArr)


1
这个 JSON.parse(JSON.stringify(arr)); 现在可以改为 structuredClone(arr) - Michael Buen

15

您可以使用ES6新增的Array.from方法,但仅支持像Map和Set等数组和可迭代对象。对于常规对象,可以使用Underscore的toArray方法或lodash的toArray方法,因为这两个库实际上对于对象而言拥有极好的支持,而不仅限于数组。如果您已经使用了underscore或lodash,则它们可以解决这个问题,并为您的对象添加各种功能性概念,例如map和reduce。


3
以下方法已在地图应用中进行了测试:
const MyMap = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

const MyArray = [...MyMap].map(item => {
  return {[item[0]]: item[1]}
});

console.info( MyArray ); //[{"a", 1}, {"b", 2}, {"c": 3}]

不是要求的 - 请参考 Array.from 的方式 - João Antunes

1
 <Your_Array> = [].concat.apply([], Array.from( <Your_IterableIterator> ));

1
将一个空数组连接到“Array.from”的结果中是完全没有意义的。 - Bergi

-3
你也可以这样做,但这两种方法都不可取(仅为完整性而证明概念):
let arr = [];
for (let elem of gen(...)){
    arr.push(elem);
}

或者使用ES5 +生成器函数的“艰难方式”(Fiddle在当前Firefox中可用):

var squares = function* (n) {
  for (var i = 0; i < n; i++) {
    yield i * i;
  }
};

var arr = [];
var gen = squares(10);
var g;
while (true) {
  g = gen.next();
  if (g.done) {
    break;
  }
  arr.push(g.value);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接