Dan*_*Dan 1638 javascript arrays
将JavaScript中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
Run Code Online (Sandbox Code Playgroud)
我意识到arr2引用相同的数组arr1,而不是一个新的独立数组.如何复制数组以获得两个独立的数组?
Sak*_*ket 2597
用这个:
var newArray = oldArray.slice();
Run Code Online (Sandbox Code Playgroud)
基本上,该slice()操作克隆数组并返回对新数组的引用.另请注意:
对于引用,字符串和数字(而不是实际对象),将slice()对象引用复制到新数组中.原始数组和新数组都引用相同的对象.如果引用的对象发生更改,则更改对新的和原始数组都可见.
字符串和数字等原语是不可变的,因此不可能更改字符串或数字.
tfm*_*gue 491
在Javascript中,深度复制技术依赖于数组中的元素.
我们从那里开始.
元素可以是:文字值,文字结构或原型.
// 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 () {}"
Run Code Online (Sandbox Code Playgroud)
从这些元素中我们可以创建三种类型的数组.
// 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 () {}];
Run Code Online (Sandbox Code Playgroud)
根据数组中元素的类型,我们可以使用各种技术进行深度复制.
文字值(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()它的性能高于JSON.parse(JSON.stringify(myArray))技术http://jsperf.com/js-deep-copy/15.
对于那些回避第三方库(如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;
}Run Code Online (Sandbox Code Playgroud)
题
var arr1 = ['a','b','c'];
var arr2 = arr1;
Run Code Online (Sandbox Code Playgroud)
我意识到arr2引用的是与arr1相同的数组,而不是一个新的独立数组.如何复制数组以获得两个独立的数组?
回答
因为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
Run Code Online (Sandbox Code Playgroud)
Luk*_*mur 182
您可以使用数组传播...来复制数组.
const itemsCopy = [...items];
此外,如果想要创建一个新数组,其中现有数组是其中的一部分:
var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
Run Code Online (Sandbox Code Playgroud)
现在所有主流浏览器都支持数组传播,但如果您需要较旧的支持,请使用typescript或babel并编译为ES5.
jon*_*ohn 152
不需要jQuery ...... 工作示例
var arr2 = arr1.slice()
Run Code Online (Sandbox Code Playgroud)
这将从阵列的起始位置0到末尾复制阵列.
重要的是要注意它将按原始类型(字符串,数字等)的预期工作,并且还解释引用类型的预期行为......
如果你有一个引用类型数组,比如类型Object.数组将被复制,但两个数组都将包含对相同数组的引用Object.所以在这种情况下,即使数组实际被复制,看起来像是通过引用复制数组.
Nin*_*non 71
替代slice是concat,可以以两种方式使用.第一个可能更具可读性,因为预期的行为非常明确:
var array2 = [].concat(array1);
Run Code Online (Sandbox Code Playgroud)
第二种方法是:
var array2 = array1.concat();
Run Code Online (Sandbox Code Playgroud)
科恩(在评论中)指出后一种方法有更好的表现.
这种方法的工作方式是该concat方法创建一个新数组,该数组由调用它的对象中的元素组成,后跟作为参数传递给它的任何数组的元素.因此,当没有传递参数时,它只是复制数组.
李Penkman,也是在评论中指出,如果有一个机会array1是undefined,你可以按照如下返回一个空数组:
var array2 = [].concat(array1 || []);
Run Code Online (Sandbox Code Playgroud)
或者,对于第二种方法:
var array2 = (array1 || []).concat();
Run Code Online (Sandbox Code Playgroud)
请注意,您也可以使用slice:var array2 = (array1 || []).slice();.
Cht*_*lek 56
这是我在尝试了许多方法后的方法:
var newArray = JSON.parse(JSON.stringify(orgArray));
Run Code Online (Sandbox Code Playgroud)
这将创建一个与第一个无关的新深拷贝(不是浅拷贝).
此外,这显然不会克隆事件和函数,但你可以在一行中做到这一点,它可以用于任何类型的对象(数组,字符串,数字,对象......)
小智 19
在处理数字或字符串等简单数据类型时,一些提到的方法效果很好,但是当数组包含其他对象时,这些方法会失败.当我们尝试将任何对象从一个数组传递到另一个数组时,它将作为引用而不是对象传递.
在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;
};
Run Code Online (Sandbox Code Playgroud)
简单地使用
var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()
Run Code Online (Sandbox Code Playgroud)
它会工作.
Lew*_*wis 15
我个人认为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);
Run Code Online (Sandbox Code Playgroud)
Wal*_*anG 11
如果您在ECMAScript 6的环境中,使用Spread Operator可以这样做:
var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');
console.log(arr1)
console.log(arr2)Run Code Online (Sandbox Code Playgroud)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>Run Code Online (Sandbox Code Playgroud)
Dev*_*vWL 11
那么我们如何复制这个 arr 呢?
let arr = [1,2,3,4,5];
Run Code Online (Sandbox Code Playgroud)
let arrCopy = [...arr];
Run Code Online (Sandbox Code Playgroud)
let arrCopy = arr.slice();
let arrCopy = [].concat(arr);
Run Code Online (Sandbox Code Playgroud)
将一个变量传递给另一个对象/数组等复合值的行为会有所不同。在 copand 值上使用 asign 运算符,我们将引用传递给一个对象。这就是为什么在删除/添加 arr 元素时两个数组的值都会发生变化的原因。
arrCopy[1] = 'adding new value this way will unreference';
Run Code Online (Sandbox Code Playgroud)
当您为变量分配一个新值时,您正在更改引用本身,它不会影响原始对象/数组。
小智 9
添加到array.slice()的解决方案; 请注意,如果您有多维数组子数组将被引用复制.你可以做的是分别循环和切片()每个子数组
var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();
arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);
function arrCpy(arrSrc, arrDis){
for(elm in arrSrc){
arrDis.push(arrSrc[elm].slice());
}
}
var arr3=[];
arrCpy(arr,arr3);
arr3[1][1] = 77;
console.log(arr3[1][1]);
console.log(arr[1][1]);
Run Code Online (Sandbox Code Playgroud)
同样的东西会转到对象数组,它们会被引用复制,你必须手动复制它们
我发现这个方法比较简单:
let arr = [1,2,3,4,5];
let newArr = [...arr];
console.log(newArr);Run Code Online (Sandbox Code Playgroud)
let a = [1,2,3];
Run Code Online (Sandbox Code Playgroud)
现在,您可以执行以下任一操作来制作数组的副本。
let b = Array.from(a);
Run Code Online (Sandbox Code Playgroud)
或者
let b = [...a];
Run Code Online (Sandbox Code Playgroud)
或者
let b = new Array(...a);
Run Code Online (Sandbox Code Playgroud)
或者
let b = a.slice();
Run Code Online (Sandbox Code Playgroud)
或者
let b = a.map(e => e);
Run Code Online (Sandbox Code Playgroud)
现在,如果我改变一个,
a.push(5);
Run Code Online (Sandbox Code Playgroud)
然后,a 是 [1,2,3,5] 但 b 仍然是 [1,2,3] 因为它有不同的参考。
但我认为,在上述所有方法中 Array.from 更好,主要用于复制数组。
当有很多答案时,您必须使用最佳实践来解决此问题。
\n我建议您使用数组扩展 \xe2\x80\xa6 来复制数组。
\nvar arr1 = ['a','b','c'];
var arr2 = [\xe2\x80\xa6arr1];
正如我们所知,在Javascript 数组和对象是通过引用,但我们可以做什么方式复制数组而不更改原来的数组?
以下是几种方法:
想象一下,我们在您的代码中有这个数组:
var arr = [1, 2, 3, 4, 5];
Run Code Online (Sandbox Code Playgroud)
1)在函数中循环遍历数组并返回一个新数组,如下所示:
function newArr(arr) {
var i=0, res = [];
while(i<arr.length){
res.push(arr[i]);
i++;
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
2)使用切片方法,切片用于切片数组的一部分,它将切片数组的某些部分而不接触原始数据,在切片中,如果不指定数组的开始和结束,它将切片整个数组和基本上是数组的完整副本,所以我们可以很容易地说:
var arr2 = arr.slice(); // make a copy of the original array
Run Code Online (Sandbox Code Playgroud)
3)也是联系方法,这是为了合并两个数组,但是我们可以只指定一个数组,然后这基本上是新联系数组中的值的副本:
var arr2 = arr.concat();
Run Code Online (Sandbox Code Playgroud)
4)也是字符串化和解析方法,不推荐,但可以是一种复制数组和对象的简单方法:
var arr2 = JSON.parse(JSON.stringify(arr));
Run Code Online (Sandbox Code Playgroud)
5)Array.from方法,这个没有被广泛支持,在使用之前检查不同浏览器中的支持:
const arr2 = Array.from(arr);
Run Code Online (Sandbox Code Playgroud)
6)ECMA6的方式,也没有完全支持,但如果你想要转换,babelJs可以帮助你:
const arr2 = [...arr];
Run Code Online (Sandbox Code Playgroud)
丹,不需要使用花哨的技巧。您需要做的就是通过执行此操作制作 arr1 的副本。
var arr1 = ['a','b','c'];
var arr2 = [];
var arr2 = new Array(arr1);
arr2.push('d'); // Now, arr2 = [['a','b','c'],'d']
console.log('arr1:');
console.log(arr1);
console.log('arr2:');
console.log(arr2);
// Following did the trick:
var arr3 = [...arr1];
arr3.push('d'); // Now, arr3 = ['a','b','c','d'];
console.log('arr3:');
console.log(arr3);Run Code Online (Sandbox Code Playgroud)
现在arr1和arr2是存储在不同堆栈中的两个不同的数组变量。
在 jsfiddle 上检查一下。
您可以将 ES6 与扩展 Opeartor 一起使用,它更简单。
arr2 = [...arr1];
Run Code Online (Sandbox Code Playgroud)
有限制..检查文档扩展语法@ mozilla
| 归档时间: |
|
| 查看次数: |
846753 次 |
| 最近记录: |