wal*_*yqs 392 javascript
...每个对象还引用同一数组中的其他对象?
当我第一次想出这个问题时,我就是这样的
var clonedNodesArray = nodesArray.clone()
Run Code Online (Sandbox Code Playgroud)
将存在并搜索有关如何在javascript中克隆对象的信息.我确实在StackOverflow上找到了一个问题(由同样的@JohnResig回答)他指出用jQuery你可以做的
var clonedNodesArray = jQuery.extend({}, nodesArray);
Run Code Online (Sandbox Code Playgroud)
克隆一个对象.我试过这个,但这只复制了数组中对象的引用.所以,如果我
nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
Run Code Online (Sandbox Code Playgroud)
nodesArray [0]和clonedNodesArray [0]的值都将变为"绿色".然后我试了一下
var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
Run Code Online (Sandbox Code Playgroud)
哪个深层复制了一个Object,但我分别从Firebug和Opera Dragonfly 那里得到了" 过多的递归 "和" 控制堆栈溢出 "的消息.
你会怎么做?这是不应该做的事吗?在Javascript中是否有可重用的方法?
Vla*_*idi 500
来吧,这是21世纪:只要你的对象包含JSON可序列化的内容(没有函数,没有Number.POSITIVE_INFINITY
等),就不需要任何循环来克隆数组或对象.这是一款纯粹的香草单线解决方案.
var clonedArray = JSON.parse(JSON.stringify(nodesArray))
Run Code Online (Sandbox Code Playgroud)
总结下面的注释,这种方法的主要优点是它还克隆了数组的内容,而不仅仅是数组本身.主要缺点是它仅限于处理JSON可序列化内容,以及它的性能(这比slice
基于方法的情况要糟糕得多).
din*_*rus 251
我用Object.assign解决了对象数组的克隆问题
__CODE__
甚至更短的扩展语法
__CODE__
Leo*_*opd 157
如果你需要的只是一个浅拷贝,一个非常简单的方法是:
new_array = old_array.slice(0);
Run Code Online (Sandbox Code Playgroud)
Dan*_*Lew 99
浅拷贝的问题是没有克隆所有对象.虽然每个对象的引用在每个数组中都是唯一的,但是一旦你最终抓住它,你就会像以前一样处理同一个对象.克隆它的方式没有任何问题......使用Array.slice()会产生相同的结果.
您的深层复制存在问题的原因是因为您最终会得到循环对象引用.Deep会尽可能地深入,如果你有一个圆圈,它会一直无限地走,直到浏览器晕倒.
如果数据结构不能表示为有向非循环图,那么我不确定您是否能够找到一种用于深度克隆的通用方法.循环图提供了许多棘手的极端情况,因为它不是常见的操作,我怀疑是否有人编写了完整的解决方案(如果它甚至可能 - 它可能不是!但我现在没有时间尝试编写严格的证据.).我在这个页面上找到了一些关于这个问题的好评.
如果你需要带有循环引用的对象数组的深层副本,我相信你将需要编写自己的方法来处理你的专用数据结构,这样它就是一个多遍克隆:
Men*_*Mez 48
最佳和最新的克隆方法如下:
使用"..."ES6扩展运算符.
这是最简单的例子:
var clonedObjArray = [...oldObjArray];
Run Code Online (Sandbox Code Playgroud)
这样我们将数组扩展为单个值,并使用[]运算符将其放入新数组中.
这是一个较长的示例,显示了它的不同工作方式:
let objArray = [ {a:1} , {b:2} ];
let refArray = objArray; // this will just point to the objArray
let clonedArray = [...objArray]; // will clone the array
console.log( "before:" );
console.log( "obj array" , objArray );
console.log( "ref array" , refArray );
console.log( "cloned array" , clonedArray );
objArray[0] = {c:3};
console.log( "after:" );
console.log( "obj array" , objArray ); // [ {c:3} , {b:2} ]
console.log( "ref array" , refArray ); // [ {c:3} , {b:2} ]
console.log( "cloned array" , clonedArray ); // [ {a:1} , {b:2} ]
Run Code Online (Sandbox Code Playgroud)
小智 25
这对我有用:
var clonedArray = $.map(originalArray, function (obj) {
return $.extend({}, obj);
});
Run Code Online (Sandbox Code Playgroud)
如果您需要数组中对象的深层副本:
var clonedArray = $.map(originalArray, function (obj) {
return $.extend(true, {}, obj);
});
Run Code Online (Sandbox Code Playgroud)
小智 18
$.evalJSON($.toJSON(origArray));
Run Code Online (Sandbox Code Playgroud)
sud*_*nna 14
如果要实现深度克隆,请使用JSON.parse(JSON.stringify(your {} or [])):
const myObj ={
a: 1,
b: 2,
b: 3
}
const deepClone = JSON.parse(JSON.stringify(myObj));
deepClone.a = 12;
console.log("deepClone-----"+myObj.a);
const withOutDeepClone = myObj;
withOutDeepClone.a = 12;
console.log("withOutDeepClone----" + myObj.a);
Run Code Online (Sandbox Code Playgroud)
Vin*_*oth 12
从2022年开始,我们可以使用structuredClone
深复制。
structuredClone(array)
Run Code Online (Sandbox Code Playgroud)
Map将从旧的数组创建新数组(不引用旧数组),并在地图内部创建新对象并迭代属性(键)并将旧Array对象的值分配给新对象的相应属性.
这将创建完全相同的对象数组.
let newArray = oldArray.map(a => {
let newObject = {};
Object.keys(a).forEach(propertyKey => {
newObject[propertyKey] = a[propertyKey];
});
return newObject ;
});
Run Code Online (Sandbox Code Playgroud)
小智 8
我可能有一个简单的方法来做到这一点,而不必做痛苦的递归和不知道所讨论的对象的所有细节.使用jQuery,只需使用jQuery将对象转换为JSON $.toJSON(myObjectArray)
,然后获取JSON字符串并将其评估回对象.BAM!做完了!问题解决了.:)
var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));
Run Code Online (Sandbox Code Playgroud)
我正在回答这个问题,因为似乎没有一个简单明确的解决方案来解决"在Javascript中克隆一个对象数组"的问题:
function deepCopy (arr) {
var out = [];
for (var i = 0, len = arr.length; i < len; i++) {
var item = arr[i];
var obj = {};
for (var k in item) {
obj[k] = item[k];
}
out.push(obj);
}
return out;
}
// test case
var original = [
{'a' : 1},
{'b' : 2}
];
var copy = deepCopy(original);
// change value in copy
copy[0]['a'] = 'not 1';
// original[0]['a'] still equals 1
Run Code Online (Sandbox Code Playgroud)
此解决方案迭代数组值,然后迭代对象键,将后者保存到新对象,然后将该新对象推送到新数组.
见jsfiddle.注:一个简单的.slice()
或[].concat()
不足够的对象中的数组.
JQuery扩展工作正常,只需要指定克隆数组而不是对象(注意[]而不是{}作为extend方法的参数):
var clonedNodesArray = jQuery.extend([], nodesArray);
Run Code Online (Sandbox Code Playgroud)
正如Daniel Lew所提到的,循环图有一些问题.如果我遇到这个问题,我会为clone()
有问题的对象添加特殊方法,或者记住我已经复制过的对象.
copyCount
每次复制代码时,我都会使用一个变量增加1.copyCount
复制具有低于当前复制过程的对象.如果不是,则应引用已存在的副本.这使得必须从原始链接到其副本.
还有一个问题:记忆.如果从一个对象到另一个对象有这个引用,浏览器可能无法释放这些对象,因为它们总是从某个地方引用.您必须进行第二次传递,将所有复制引用设置为Null.(如果你这样做,你就不必拥有copyCount
一个布尔isCopied
就足够了,因为你可以重置第二遍中的值.)
此方法非常简单,您可以修改克隆而不修改原始数组。
// Original Array
let array = [{name: 'Rafael'}, {name: 'Matheus'}];
// Cloning Array
let clone = array.map(a => {return {...a}})
// Editing the cloned array
clone[1].name = 'Carlos';
console.log('array', array)
// [{name: 'Rafael'}, {name: 'Matheus'}]
console.log('clone', clone)
// [{name: 'Rafael'}, {name: 'Carlos'}]
Run Code Online (Sandbox Code Playgroud)
lodash具有以下cloneDeep
功能:
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
315493 次 |
最近记录: |