Javascript 按值复制数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7486085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copy array by value
提问by Dan
When copying an array in JavaScript to another array:
将 JavaScript 中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
I realized that arr2
refers to the same array as arr1
, rather than a new, independent array. How can I copy the array to get two independent arrays?
我意识到它arr2
指的是与 相同的数组arr1
,而不是一个新的、独立的数组。如何复制数组以获得两个独立的数组?
回答by Saket
Use this:
用这个:
var newArray = oldArray.slice();
Basically, the slice()
operation clones the array and returns a reference to a new array.
基本上,该slice()
操作会克隆数组并返回对新数组的引用。
Also note that:
另请注意:
For references, strings and numbers (and not the actual object), slice()
copies object references into the new array.Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.
对于引用、字符串和数字(而不是实际对象),将slice()
对象引用复制到新数组中。原始数组和新数组都指向同一个对象。如果引用的对象发生更改,则更改对新数组和原始数组都可见。
Primitives such as strings and numbers are immutable, so changes to the string or number are impossible.
字符串和数字等原语是不可变的,因此不可能更改字符串或数字。
回答by tfmontague
In Javascript, deep-copy techniques depend on the elements in an array. Let's start there.
在 Javascript 中,深度复制技术依赖于数组中的元素。让我们从那里开始。
Three types of elements
三种元素
Elements can be: literal values, literal structures, or prototypes.
元素可以是:文字值、文字结构或原型。
// Literal values (type1)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';
// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};
// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}`
From these elements we can create three types of arrays.
从这些元素我们可以创建三种类型的数组。
// 1) Array of literal-values (boolean, number, string)
const type1 = [true, 1, "true"];
// 2) Array of literal-structures (array, object)
const type2 = [[], {}];
// 3) Array of prototype-objects (function)
const type3 = [function () {}, function () {}];
Deep copy techniques depend on the three array types
深拷贝技术取决于三种数组类型
Based on the types of elements in the array, we can use various techniques to deep copy.
根据数组中元素的类型,我们可以使用各种技术进行深度复制。
Array of literal-values (type1)
The[...myArray]
,myArray.splice(0)
,myArray.slice()
, andmyArray.concat()
techniques can be used to deep copy arrays with literal values (boolean, number, and string) only; where the Spread operator[...myArray]
has the best performance (https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat).Array of literal-values (type1) and literal-structures (type2)
TheJSON.parse(JSON.stringify(myArray))
technique can be used to deep copy literal values (boolean, number, string) and literal structures (array, object), but not prototype objects.All arrays (type1, type2, type3)
The jQuery$.extend(myArray)
technique can be used to deep-copy all array-types. Libraries like Underscoreand Lo-dashoffer similar deep-copy functions to jQuery$.extend()
, yet have lower performance. More surprisingly,$.extend()
has higher performance than theJSON.parse(JSON.stringify(myArray))
technique http://jsperf.com/js-deep-copy/15.
And for those developers that shy away from third-party libraries (like jQuery), you can use the following custom function; which has higher performance than $.extend, and deep-copies all arrays.
文字值(TYPE1)的阵列
的[...myArray]
,myArray.splice(0)
,myArray.slice()
,和myArray.concat()
技术可以被用于在只文字值(布尔,数字和字符串)深层副本阵列; 其中 Spread 运算符[...myArray]
具有最佳性能(https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat)。文字值数组 (type1) 和文字结构 (type2)
该JSON.parse(JSON.stringify(myArray))
技术可用于深度复制文字值(布尔值、数字、字符串)和文字结构(数组、对象),但不能用于原型对象。所有数组(type1、type2、type3)
jQuery$.extend(myArray)
技术可用于深度复制所有数组类型。Underscore和Lo-dash等库提供了与jQuery类似的深度复制功能$.extend()
,但性能较低。更令人惊讶的是,$.extend()
比http://jsperf.com/js-deep-copy/15JSON.parse(JSON.stringify(myArray))
技术具有更高的性能。 对于那些回避第三方库(如 jQuery)的开发人员,您可以使用以下自定义函数;它比 $.extend 具有更高的性能,并且可以深度复制所有数组。
function copy(aObject) {
if (!aObject) {
return aObject;
}
let v;
let bObject = Array.isArray(aObject) ? [] : {};
for (const k in aObject) {
v = aObject[k];
bObject[k] = (typeof v === "object") ? copy(v) : v;
}
return bObject;
}
So to answer the question...
所以要回答这个问题...
Question
题
var arr1 = ['a','b','c'];
var arr2 = arr1;
I realized that arr2 refers to the same array as arr1, rather than a new, independent array. How can I copy the array to get two independent arrays?
我意识到 arr2 指的是与 arr1 相同的数组,而不是一个新的独立数组。如何复制数组以获得两个独立的数组?
Answer
回答
Because arr1
is an array of literal values (boolean, number, or string), you can use any deep copy technique discussed above, where the spread operator ...
has the highest performance.
因为arr1
是文字值数组(布尔值、数字或字符串),您可以使用上面讨论的任何深度复制技术,其中扩展运算符...
具有最高性能。
// Highest performance for deep copying literal values
arr2 = [...arr1];
// Any of these techniques will deep copy literal values as well,
// but with lower performance.
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
回答by Luke Femur
You can use array spreads ...
to copy arrays.
您可以使用数组扩展...
来复制数组。
const itemsCopy = [...items];
const itemsCopy = [...items];
Also if want to create a new array with the existing one being part of it:
另外,如果要创建一个新数组,其中现有数组是其中的一部分:
var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
Array spreads are now supported in all major browsersbut if you need older support use typescript or babel and compile to ES5.
现在所有主要浏览器都支持数组展开,但如果您需要旧的支持,请使用 typescript 或 babel 并编译为 ES5。
回答by jondavidjohn
No jQuery needed... Working Example
不需要 jQuery... 工作示例
var arr2 = arr1.slice()
This copys the array from the starting position 0
through the end of the array.
这会将数组从起始位置复制到数组0
末尾。
It is important to note that it will work as expected for primitive types (string, number, etc.), and to also explain the expected behavior for reference types...
重要的是要注意它对于原始类型(字符串、数字等)将按预期工作,并且还解释了引用类型的预期行为......
If you have an array of Reference types, say of type Object
. The array willbe copied, but both of the arrays will contain references to the same Object
's. So in this case it would seem like the array is copied by reference even though the array is actually copied.
如果你有一个引用类型的数组,比如 type Object
。该数组将被复制,但两个数组都将包含对相同Object
's 的引用。因此,在这种情况下,即使数组实际上是复制的,它似乎也是通过引用复制的。
回答by Ninjakannon
An alternative to slice
is concat
, which can be used in 2 ways. The first of these is perhaps more readable as the intended behaviour is very clear:
的替代方法slice
是concat
,它可以以两种方式使用。其中第一个可能更具可读性,因为预期行为非常明确:
var array2 = [].concat(array1);
The second method is:
第二种方法是:
var array2 = array1.concat();
Cohen (in the comments) pointed out that this latter method has better performance.
Cohen(在评论中)指出后一种方法具有更好的性能。
The way this works is that the concat
method creates a new array consisting of the elements in the object on which it is called followed by the elements of any arrays passed to it as arguments. So when no arguments are passed, it simply copies the array.
其工作方式是该concat
方法创建一个新数组,该数组由调用它的对象中的元素组成,后跟作为参数传递给它的任何数组的元素。所以当没有传递参数时,它只是简单地复制数组。
Lee Penkman, also in the comments, points out that if there's a chance array1
is undefined
, you can return an empty array as follows:
Lee Penkman 也在评论中指出,如果有机会array1
is undefined
,您可以返回一个空数组,如下所示:
var array2 = [].concat(array1 || []);
Or, for the second method:
或者,对于第二种方法:
var array2 = (array1 || []).concat();
Note that you can also do this with slice
: var array2 = (array1 || []).slice();
.
请注意,您也可以使用slice
:执行此操作var array2 = (array1 || []).slice();
。
回答by Chtiwi Malek
This is how I've done it after trying many approaches:
在尝试了多种方法后,我是这样做的:
var newArray = JSON.parse(JSON.stringify(orgArray));
This will create a new deep copy not related to the first one (not a shallow copy).
这将创建一个与第一个无关的新深拷贝(不是浅拷贝)。
Also this obviously will not clone events and functions, but the good thing you can do it in one line, and it can be used for any kind of object (arrays, strings, numbers, objects ...)
此外,这显然不会克隆事件和函数,但是你可以在一行中完成它的好事,它可以用于任何类型的对象(数组、字符串、数字、对象......)
回答by sarvesh singh
Some of mentioned methods work well when working with simple data types like number or string, but when the array contains other objects these methods fail. When we try to pass any object from one array to another it is passed as a reference, not the object.
提到的一些方法在处理简单的数据类型(如数字或字符串)时效果很好,但是当数组包含其他对象时,这些方法就会失败。当我们尝试将任何对象从一个数组传递到另一个数组时,它是作为引用传递的,而不是对象。
Add the following code in your JavaScript file:
在您的 JavaScript 文件中添加以下代码:
Object.prototype.clone = function() {
var newObj = (this instanceof Array) ? [] : {};
for (i in this) {
if (i == 'clone')
continue;
if (this[i] && typeof this[i] == "object") {
newObj[i] = this[i].clone();
}
else
newObj[i] = this[i]
} return newObj;
};
And simply use
并简单地使用
var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()
It will work.
它会起作用。
回答by Boopathi Rajaa
From ES2015,
从 ES2015 开始,
var arr2 = [...arr1];
回答by Lewis
I personally think Array.fromis a more readable solution. By the way, just beware of its browser support.
我个人认为Array.from是一个更具可读性的解决方案。顺便说一句,请注意它的浏览器支持。
//clone
let x = [1,2,3];
let y = Array.from(x);
//deep clone
let clone = arr => Array.from(arr,item => Array.isArray(item) ? clone(item) : item);
let x = [1,[],[[]]];
let y = clone(x);
回答by ulou
Important!
重要的!
Most of answers here works for particular cases.
这里的大多数答案适用于特定情况。
If you don't care about deep/nested objects and props use (ES6):
如果您不关心深层/嵌套对象和道具使用(ES6):
let clonedArray = [...array]
let clonedArray = [...array]
but if you want to do deep clone use this instead:
但是如果你想进行深度克隆,请改用这个:
let cloneArray = JSON.parse(JSON.stringify(array))
let cloneArray = JSON.parse(JSON.stringify(array))
For lodash users:
对于 lodash 用户:
let clonedArray = _.clone(array)
documentation
let clonedArray = _.clone(array)
文件
and
和
let clonedArray = _.cloneDeep(array)
documentation
let clonedArray = _.cloneDeep(array)
文件