2016-11-11 98 views
13

使用Array.from(document.querySelectorAll('div'))还是[...document.querySelectorAll('div')]有什么区别?Array.from()vs spread syntax

这里是一个例子:

let spreadDivArray = [...document.querySelectorAll('div')]; 
console.log(spreadDivArray); 

let divArrayFrom = Array.from(document.querySelectorAll('div')); 
console.log(divArrayFrom); 

console.log()的将记录相同的结果。

是否有任何性能差异?

+0

扩展运算符的好处是它支持'Object'。 performance .. idk –

+0

要了解是否有任何性能差异,请运行基准测试。根据您是在本地ES6环境还是转换到ES5,结果可能会有很大不同。 – 2016-11-11 12:46:08

+6

主要区别在于'Array.from'可以处理没有实现迭代器协议(即Symbol.iterator)的类似数组的对象。即使使用ES6和新的浏览器规格,这些规格也越来越少。 – nils

回答

1

区别在于扩展允许数组为扩展。而from()创建了一个新的阵列。 .from()不会扩展任何内容,它会根据提供的数据创建一个新数组;另一方面,扩展运算符可以扩展具有新属性的数组。

+4

好吧,数组文字总是创建* new *数组... – Bergi

+2

我不确定是否我只是误解你的措辞,但你是否建议spread运算符改变数组而不是创建一个新的数组? – Bergi

+0

@Bergi扩散算子不会创建数组。 OP示例中的数组创建是通过扩展运算符周围的方括号完成的。 –

-1

使用Babel是一种很好的方法来查看内部发生了什么。尽管如此,我们还是想请教一下。确保Babel中选择了最新版本,因为默认设置是错误的。

使用上面的示例,这是输出。

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 

var spreadDivArray = [].concat(_toConsumableArray(document.querySelectorAll('div'))); 
console.log(spreadDivArray); 

var divArrayFrom = Array.from(document.querySelectorAll('div')); 
console.log(divArrayFrom); 
+2

如果节点列表不是可扩展的,'[] .concat'似乎不起作用?这是一个Babel输出吗? – Bergi

+0

'这是一个Babel输出吗?的确,我只是将代码复制到了babeljs.io,你有没有一个例子呢?也许babel会在需要时进行其他转换。这当然只是针对这个特定的情况进行测试。 – Keith

+2

babeljs.io repl有一些奇怪的选项,它不是很可靠。使用'[] .concat'是不正确的简化(对数组参数的扩展语法只做相同的处理),这可能是由于Babel中的错误或未知设置造成的。 – Bergi

5

那么,Array.from是一个静态方法,即,而spread语法的功能是数组文本语法的一部分。你可以像数据一样传递函数,你可以调用它们一次,几次或根本不调用它们。这在spread语法中是不可能的,在这方面它是静态的。

@nils已经指出的另一个区别是,Array.from也适用于类似数组的对象,它们没有实现可迭代协议。 spread另一方面需要迭代。

+0

“Array.from也适用于类似数组的对象,它不会实现可迭代协议” - 您能给出一个这样的对象的例子吗? – mpen

+0

没关系,[Michał举了一个例子](https://stackoverflow.com/a/40549565/65387)。 – mpen

8

传播元件it's not an operator)仅适用于那些对象iterable(即实现@@iterator方法)。 Array.from()也适用于类似数组的对象(即具有length属性和索引元素的对象),这些对象不可迭代。看到这个例子:

const arrayLikeObject = { 0: 'a', 1: 'b', length: 2 }; 
 

 
// This logs ['a', 'b'] 
 
console.log(Array.from(arrayLikeObject)); 
 
// This throws TypeError: arrayLikeObject[Symbol.iterator] is not a function 
 
console.log([...arrayLikeObject]);

另外,如果你只是想的东西转换成阵,我认为这是更好地使用Array.from(),因为它更具有可读性。例如,当你想连接多个数组时,扩展元素很有用(['a', 'b', ...someArray, ...someOtherArray])。

+0

虽然我同意'Array.from()'是一个非常可读的方式来实现这一点,我觉得传播元素语法'... arrayLikeObject'就像人们可读(或更多)。 – qarthandso