传播语法与切片方法

spread syntax vs slice method

我试图通过以下方法了解扩展语法与切片方法之间的区别。

假设我想制作一个数组的实际副本,我可能可以使用展开语法轻松完成

var fruits = ["Banana", "Chips" , "Orange", "Lemon", "Apple", "Mango"]
var newCitrus = [...fruits]

如果我console.log这个

["Banana", "Chips", "Orange", "Lemon", "Apple", "Mango"] 

但我也可以使用 slice 方法创建数组的副本。考虑到上面的相同数组,如果我做这样的事情...

var citrus = fruits.slice(0);

然后控制台记录它,它会给我完全相同的数组,我会通过传播语法得到这个数组

["Banana", "Chips", "Orange", "Lemon", "Apple", "Mango"] 

因为两者到code/write的时间差不多,所以这里有什么区别?我通常应该选择哪种方法?

性能将取决于其运行所在的引擎。与大多数 Javscript 代码一样,在各种不同的引擎中它可能是 运行。所以,使用任何感觉美观的东西。对我来说,这是传播。

... 是纯粹的美。

如果您决定使用 slice,请跳过 0,只说 .slice()

撇开性能不谈 slice 只是 Array.prototype 上的一个函数,因此它仅适用于数组。另一方面,传播语法适用于任何可迭代对象(满足 iterable protocol) so it will work out of the box on any String, Array, TypedArray, Map and Set. You can also easily create custom iterables.

sliceing 和 spreading 带孔数组(稀疏数组)也有区别。正如您在下面看到的,slice 将保留稀疏性,而 spread 将用 undefined.

填充空洞
Array(3)         // produces sparse array: [empty × 3]
Array(3).slice() // produces [empty × 3]
[...Array(3)]    // produces [undefined, undefined, undefined]

扩展语法也可用于制作对象的浅克隆:

const obj = { foo: 'bar', baz: 42 };
const clone = { ...obj };
obj.foo === clone.foo // true
obj.baz === clone.baz // true
obj === clone         // false (references are different)

Measuring in Chrome 表明 slice 的性能远高于展开运算符,每秒 67M 次操作,而每秒 4M 次操作。如果您正在构建 Chrome 或 Electron 应用程序(使用 Chromium),我会选择切片,尤其是对于大数据和实时应用程序。

编辑:

似乎 Spread 运算符现在快得多,尽管仍然比 Slice 慢:

Chrome (72+) 的新版本似乎消除了性能差距。 https://measurethat.net/Benchmarks/ListResults/2667

虽然这两种方法实际上并不等同。 Slice 是 Array.prototype 上的一个函数,并且知道数组的实现。它将创建一个非常有效的副本。但更重要的是,.slice() 将保留数组的稀疏信息。

相比之下,[...Array] 只会从现有数组的可迭代视图创建一个新数组。不一定高效。

试试这个:

var a = [];
a.length = 3;
console.log("slice:", a.slice());
console.log("spread:", [...a]);

使用 Chrome 浏览器开发者控制台,我得到了这些结果:

slice: (3) [empty × 3]
spread: (3) [undefined, undefined, undefined]

如果你的数组特别大+稀疏,array.slice()会特别快。 [...array] 可能会挂起您的浏览器。