在 JavaScript 中复制数组的最快方法 - 切片与“for”环形
为了在 JavaScript 中复制数组:使用以下哪一个更快?
Slice
方法
var dup_array = original_array.slice();
For
循环
for(var i = 0, len = original_array.length; i < len; ++i)
dup_array[i] = original_array[i];
我知道这两种方法都只进行浅复制:如果 original_array
包含对对象、对象的引用不会被克隆,但只会复制引用,因此两个数组将具有对相同对象的引用。
但这不是这个问题的重点。
我只问速度。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
如果您想要 JS 中的真实克隆对象/数组,其中包含所有属性和子对象的克隆引用:
所有其他操作都不会创建克隆,因为它们只是更改根元素的基地址,而不是所包含对象的基地址。
除非您递归遍历对象树。
对于简单的副本,这些都可以。对于存储地址相关操作,我建议(在大多数其他情况下,因为这很快!)将类型转换为字符串,然后返回一个完整的新对象。
If you want a REAL cloned object/array in JS with cloned references of all attributes and sub-objects:
ALL other operations do not create clones, because they just change the base address of the root element, not of the included objects.
Except you traverse recursive through the object-tree.
For a simple copy, these are OK. For storage address relevant operations I suggest (and in most all other cases, because this is fast!) to type convert into string and back in a complete new object.
如果您正在使用切片,它用于从数组中复制元素并创建具有相同编号的克隆。元素或更少。的元素。
If you are taking about slice it is used to copy elements from an array and create a clone with same no. of elements or less no. of elements.
2024 年 5 月
Chrome
Firefox
从未完成此基准测试,这肯定是基准测试工具的问题。
https://jsben.ch/lO6C5
另外,structuralClone 现在可用,但速度非常慢 (3%)
May 2024
Chrome
Firefox
never finishes this benchmark, certainly an issue with the benchmarking tool.
https://jsben.ch/lO6C5
Also, structuredClone is now available which is very slow (3%)
至少有 6 (!) 种克隆数组的方法:
slice
Array.from()
concat
A.map(function(e){return e;});
已经有一个huuuge BENCHMARKS 线程,提供以下信息:
对于 blink 浏览器
slice()
是最快的方法,concat()< /code> 慢一点,而
while 循环
慢 2.4 倍。对于其他浏览器,
while循环
是最快的方法,因为这些浏览器没有针对slice
和concat
进行内部优化。2016 年 7 月仍然如此。
下面是一些简单的脚本,您可以将其复制粘贴到浏览器的控制台中并运行多次以查看图片。它们输出毫秒,越低越好。
while 循环
slice
请注意,这些方法将克隆 Array 对象本身,但数组内容是通过引用复制的,而不是深度克隆。
There are at least 6 (!) ways to clone an array:
slice
Array.from()
concat
A.map(function(e){return e;});
There has been a huuuge BENCHMARKS thread, providing following information:
for blink browsers
slice()
is the fastest method,concat()
is a bit slower, andwhile loop
is 2.4x slower.for other browsers
while loop
is the fastest method, since those browsers don't have internal optimizations forslice
andconcat
.This remains true in Jul 2016.
Below are simple scripts that you can copy-paste into your browser's console and run several times to see the picture. They output milliseconds, lower is better.
while loop
slice
Please note that these methods will clone the Array object itself, array contents however are copied by reference and are not deep cloned.
从技术上讲,切片是最快的方法。 但是,如果添加
0
开始索引,速度会更快。更快
比https://jsben.ch/F0SZ3
Technically
slice
is the fastest way. However, it is even faster if you add the0
begin index.is faster than
https://jsben.ch/F0SZ3
es6方式怎么样?
what about es6 way?
深度克隆数组或对象的最简单方法:
Easiest way to deep clone Array or Object:
???? Fastest Way to Clone an Array
I made this very plain utility function to test the time that it takes to clone an array. It is not 100% reliable. However, it can give you a bulk idea as to how long it takes to clone an existing array:
And tested different approaches:
UPDATES
JSON.parse(JSON.stringify(arr))
null
.Thank you @GilEpshtain for this update.
我整理了一个快速演示: http://jsbin.com/agugo3/edit
我在互联网上的结果 ;Explorer 8 为 156、782 和 750,这表明
slice
在这种情况下要快得多。I put together a quick demo: http://jsbin.com/agugo3/edit
My results on Internet Explorer 8 are 156, 782, and 750, which would indicate
slice
is much faster in this case.a.map(e => e)
是这项工作的另一种选择。截至目前,.map()
在 Firefox 中速度非常快(几乎与.slice(0)
一样快),但在 Chrome 中则不然。另一方面,如果数组是多维的,由于数组是对象而对象是引用类型,因此切片或连接方法都无法解决问题......因此克隆数组的一种正确方法是发明 <代码>Array.prototype.clone()如下。
a.map(e => e)
is another alternative for this job. As of today.map()
is very fast (almost as fast as.slice(0)
) in Firefox, but not in Chrome.On the other hand, if an array is multi-dimensional, since arrays are objects and objects are reference types, none of the slice or concat methods will be a cure... So one proper way of cloning an array is an invention of
Array.prototype.clone()
as follows.克隆对象数组的最快方法是使用扩展运算符,
但克隆数组内的对象仍将指向旧的内存位置。因此,对 clonedArray 对象的更改也会更改 orignalArray。因此,
这不仅会创建新数组,还会将对象克隆到其中。
免责声明如果您正在使用嵌套对象,在这种情况下扩展运算符将作为浅克隆工作。那时最好使用
Fastest way to clone an Array of Objects will be using spread operator
but the objects inside that cloned array will still pointing at the old memory location. hence change to clonedArray objects will also change the orignalArray. So
this will not only create new array but also the objects will be cloned to.
disclaimer if you are working with nested object in that case spread operator will work as SHALLOW CLONE. At that point better to use
请查看:链接。重要的不是速度,而是舒适度。此外,如您所见,您只能在基本类型上使用slice(0)。
要制作数组的独立副本而不是对其引用的副本,可以使用数组切片方法。
例子:
来源:链接
Take a look at: link. It's not about speed, but comfort. Besides as you can see you can only use slice(0) on primitive types.
To make an independent copy of an array rather than a copy of the refence to it, you can use the array slice method.
Example:
Source: link
使用
Spread
运算符的 ECMAScript 2015 方式:基本示例:
在浏览器控制台中尝试:
参考文献
ECMAScript 2015 way with the
Spread
operator:Basic examples:
Try in the browser console:
References
正如@Dan所说“这个答案很快就会过时。使用基准来检查实际情况”, jsperf 有一个具体的答案,但它本身还没有答案: while:
had 960,589 ops/sec with the runnerup
a.concat()
at 578,129 ops/sec ,即 60%。这是最新的 Firefox (40) 64 位。
@aleclarson 创建了一个新的、更可靠的基准。
As @Dan said "This answer becomes outdated fast. Use benchmarks to check the actual situation", there is one specific answer from jsperf that has not had an answer for itself: while:
had 960,589 ops/sec with the runnerup
a.concat()
at 578,129 ops/sec, which is 60%.This is the lastest Firefox (40) 64 bit.
@aleclarson created a new, more reliable benchmark.
基准时间!
我的结果:
Chrome(V8引擎):
Firefox(SpiderMonkey引擎):
Benchmark time!
My results:
Chrome (V8 engine):
Firefox (SpiderMonkey Engine):
这取决于浏览器。如果您查看博客文章Array.prototype.slice 与手动创建数组,每个都有一个粗略的性能指南:
结果:
It depends on the browser. If you look in the blog post Array.prototype.slice vs manual array creation, there is a rough guide to performance of each:
Results:
有一种更简洁的解决方案:
需要进行长度检查,因为 Array 构造函数在仅使用一个参数调用时的行为有所不同。
There is a much cleaner solution:
The length check is required, because the
Array
constructor behaves differently when it is called with exactly one argument.请记住 .slice() 不适用于二维数组。你需要一个像这样的函数:
Remember .slice() won't work for two-dimensional arrays. You'll need a function like this:
这取决于数组的长度。如果数组长度 <= 1,000,000,则
slice
和concat
方法花费的时间大致相同。但是,当您提供更广泛的范围时,concat
方法会获胜。例如,尝试以下代码:
如果将original_array 的长度设置为 1,000,000,则
slice
方法和concat
方法花费的时间大约相同(3-4 毫秒,取决于随机数)。如果将 Original_array 的长度设置为 10,000,000,则
slice
方法将花费超过 60 毫秒,而concat
方法将花费超过 20 毫秒。It depends on the length of the array. If the array length is <= 1,000,000, the
slice
andconcat
methods are taking approximately the same time. But when you give a wider range, theconcat
method wins.For example, try this code:
If you set the length of original_array to 1,000,000, the
slice
method andconcat
method are taking approximately the same time (3-4 ms, depending on the random numbers).If you set the length of original_array to 10,000,000, then the
slice
method takes over 60 ms and theconcat
method takes over 20 ms.在 ES6 中,您可以简单地利用 Spread 语法。
示例:
请注意,展开运算符会生成一个全新的数组,因此修改一个数组不会影响另一个数组。
例子:
In ES6, you can simply utilize the Spread syntax.
Example:
Please note that the spread operator generates a completely new array, so modifying one won't affect the other.
Example:
我是从另一个关于浅克隆数组的问题重定向到这里的,在发现大多数链接要么死了、过时或损坏后,我想我会发布一个可以在自己的环境中运行的解决方案。
以下代码应该半准确地测量使用特定方式克隆数组所需的时间。您可以使用开发者控制台或 Node.JS 在浏览器中直接运行它。您始终可以在此处找到它的最新版本。
我已经运行了几个尺寸,但这里有 16384 个元素数据的副本:
总体而言,以下情况似乎为真:
array.slice()
, (arraySlice0)array.slice(0)
和 (arrayConcat)[].concat(array)
速度相当快。 arraySlice 似乎速度更快。Object.assign([], array)
在处理大量数组时速度更快,但会带来消除任何未定义
条目的缺点。New Array(...array)
、(arrayMap)array.map(i => i)
、 (objectValues)Object.values(array)
, (objectAssign)Object.assign(array)
, (json)JSON.parse(JSON.stringify(array)
, (loop)let arr = new Array(); for (let e of array) { arr.push(e); return arr };
免责声明:这些结果来自我的个人系统,我保留在我的代码中犯错误的权利。
I was redirected here from another question about shallow cloning Arrays, and after finding out that most of the links are either dead, outdated, or broken, figured I'd post a solution that you can just run in your own environment.
The following code should semi-accurately measure how much time it takes to clone an array using specific ways. You can run it in your Browser directly using the Developer console or Node.JS. The latest version of it can always be found here.
I've run this for a few sizes, but here's a copy of the 16384 element data:
Overall, it appears as if the following is true:
array.slice()
, (arraySlice0)array.slice(0)
and (arrayConcat)[].concat(array)
are equivalently fast. arraySlice appears to be minimally faster.Object.assign([], array)
is faster with massive arrays, but brings the downside of eliminating any entries that areundefined
.New Array(...array)
, (arrayMap)array.map(i => i)
, (objectValues)Object.values(array)
, (objectAssign)Object.assign(array)
, (json)JSON.parse(JSON.stringify(array)
, (loop)let arr = new Array(); for (let e of array) { arr.push(e); }; return arr; }
.Disclaimer: These results are from my personal system, and I reserve the right to have made an error in my code.
因此,为了避免这些情况发生,请使用
So, in order to avoid these scenarios to happen, use
克隆数组的方法有多种。基本上,克隆有两种分类方式:
例子 :
There were several ways to clone an array. Basically, Cloning was categorized in two ways:
Example :
一个简单的解决方案:
A simple solution:
在 JavaScript 中按顺序复制数组的快速方法:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
如果你数组对象包含一些 JSON 不可序列化的内容(函数、Number.POSITIVE_INFINITY 等)更好用
array1copy = JSON.parse(JSON.stringify(array1))
Fast ways to duplicate an array in JavaScript in Order:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
If your array objects contain some JSON-non-serializable content (functions, Number.POSITIVE_INFINITY, etc.) better to use
array1copy = JSON.parse(JSON.stringify(array1))
您可以按照此代码操作。不可变方式数组克隆。这是阵列克隆的完美方式
You can follow this code. Immutable way array clone. This is the perfect way to array cloning