【问题标题】:spread syntax vs slice method传播语法与切片方法
【发布时间】:2018-12-12 08:00:29
【问题描述】:

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

假设我想制作一个数组的实际副本,我可以使用扩展语法轻松地做到这一点

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

如果我控制台记录这个

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

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

var citrus = fruits.slice(0);

然后在控制台记录它,它会给我通过扩展语法得到的完全相同的数组

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

由于他们都需要大约相同的时间来编码/编写,这里有什么区别?我通常应该选择哪种方法?

【问题讨论】:

  • spread 运算符比 Firefox 中的 slice 大约 5% faster - spread 运算符比 Chrome 中的 slice 大约 60% SLOWER - 所以,你会使用传播运算符让人们相信 Chrome 比 Firefox 慢
  • slice 允许更多地控制数组的哪一部分,而扩展运算符允许快速“粘贴”到数组中,例如["other", "elements", ...fruits].
  • @JaromandaX 我建议[...arr].slice() 满足所有用户
  • @Mark_M - 所以,不是[].concat([...arr].slice())
  • @JaromandaX 实际上很重要。我见过有人问诸如“为什么我不能var args = ...arguments;”之类的问题,答案是因为它不是运算符

标签: javascript slice spread-syntax


【解决方案1】:

除了性能之外slice 只是Array.prototype 上的一个函数,因此它仅适用于数组。另一方面,扩展语法适用于任何可迭代(满足iterable protocol 的对象),因此它可以在任何StringArrayTypedArrayMapSet 上开箱即用。你也可以轻松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)

【讨论】:

    【解决方案2】:

    这两种方法实际上并不等效。 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] 可能会挂起你的浏览器。

    【讨论】:

    • 谢谢。我删除了“深”这个词,但它实际上也不是“浅”:“它从原始数组返回一个 元素的浅拷贝。原始数组的元素被复制到返回的数组中”(强调我的)。我猜你可以说它只是一个标准副本,正如你在任何基于引用的语言中所期望的那样:数组是新的,数组中的引用没有改变。
    【解决方案3】:

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

    编辑:

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

    【讨论】:

    • 在当前的 Chrome 上运行基准测试并获得 75,333,251 操作/秒与 68,604,739 操作/秒。看起来传播运算符在当前版本中改进了很多
    • Spread Operator 在 Firefox Safari 和 Chrome Mobile IOS 中更快
    • 看起来传播速度更快measurethat.net/Benchmarks/Show/2667/0/…
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      性能将取决于其运行所在的引擎。与大多数 JavaScript 代码一样,它可能会在各种不同的引擎中运行。所以,使用任何在美学上感觉更好的东西。对我来说,这很普遍。

      ... 美不胜收。

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

      【讨论】:

        猜你喜欢
        • 2017-03-25
        • 2017-12-13
        • 2023-04-04
        • 1970-01-01
        • 2012-11-22
        • 2011-08-08
        • 2018-10-14
        • 2019-04-16
        • 2012-05-16
        相关资源
        最近更新 更多