我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
当前回答
我已经完成了上述所有解决方案,它们都很好。然而,您可以使用另一种方法来克隆对象(值不引用)。对象分配
let x = {
a: '1',
b: '2'
}
let y = Object.assign({}, x)
y.a = "3"
console.log(x)
输出将为
{ a: '1', b: '2' }
此外,您还可以使用相同的方法克隆阵列。
clonedArray = Object.assign([], array)
其他回答
这里许多同行针对深度克隆提出的解决方案JSON.parse(JSON.stringify(orig_obj)有几个问题,我发现这些问题如下:
它在复制原始对象中未定义值的条目时丢弃这些条目,如果有一些值,如Infinity、NaN等,它们将在复制时转换为null,如果原始对象中存在Date类型,则它将在克隆对象中字符串化(typeof Date_entry-->string)。
找到了一种克隆对象的有效方法,它在各种场景中都很适合我。请看一看下面的代码,因为它已经解决了JSON.parse(…)的所有上述缺陷,但最终实现了正确的深度克隆:
var orig_obj = {
string: 'my_str',
number: 123,
bool: false,
nul: null,
nested : {
value : true
},
nan : NaN,
date: new Date(),
undef: undefined,
inf: Infinity,
}
console.log("original_obj before modification: ", orig_obj, "\n");
console.log(typeof orig_obj.date, "\n");
var clone_obj = Object.assign({}, orig_obj);
//this below loop will help in deep cloning and solving above issues
for(let prop in orig_obj) {
if(typeof orig_obj[prop] === "object") {
if(orig_obj[prop] instanceof Date)
clone_obj[prop] = orig_obj[prop];
else {
clone_obj[prop] = JSON.parse(JSON.stringify(orig_obj[prop]));
}
}
}
console.log("cloned_obj before modification: ", orig_obj, "\n");
clone_obj.bool = true;
clone_obj.nested.value = "false";
console.log("original_obj post modification: ", orig_obj, "\n");
console.log("cloned_obj post modification: ", clone_obj, "\n");
console.log(typeof clone_obj.date);
我已经在标量对象的情况下尝试过这一点,它对我很有用:
function binder(i) {
return function () {
return i;
};
}
a=1;
b=binder(a)(); // copy value of a into b
alert(++a); // 2
alert(b); // still 1
当做
使用npm的深度复制。在浏览器和节点中作为npm模块工作。。。
https://www.npmjs.com/package/deepcopy
设a=深度复制(b)
如果你对一个浅拷贝没有问题,underscore.js库有一个克隆方法。
y = _.clone(x);
或者你可以像
copiedObject = _.extend({},originalObject);
这是对A.Levy代码的修改,以处理函数和多个/循环引用的克隆。这意味着,如果克隆的树中的两个财产是同一对象的引用,则克隆的对象树将使这些财产指向被引用对象的同一克隆。这也解决了循环依赖性的问题,如果不加以处理,就会导致无限循环。算法的复杂度为O(n)
function clone(obj){
var clonedObjectsArray = [];
var originalObjectsArray = []; //used to remove the unique ids when finished
var next_objid = 0;
function objectId(obj) {
if (obj == null) return null;
if (obj.__obj_id == undefined){
obj.__obj_id = next_objid++;
originalObjectsArray[obj.__obj_id] = obj;
}
return obj.__obj_id;
}
function cloneRecursive(obj) {
if (null == obj || typeof obj == "string" || typeof obj == "number" || typeof obj == "boolean") return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0; i < obj.length; ++i) {
copy[i] = cloneRecursive(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
if (clonedObjectsArray[objectId(obj)] != undefined)
return clonedObjectsArray[objectId(obj)];
var copy;
if (obj instanceof Function)//Handle Function
copy = function(){return obj.apply(this, arguments);};
else
copy = {};
clonedObjectsArray[objectId(obj)] = copy;
for (var attr in obj)
if (attr != "__obj_id" && obj.hasOwnProperty(attr))
copy[attr] = cloneRecursive(obj[attr]);
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
var cloneObj = cloneRecursive(obj);
//remove the unique ids
for (var i = 0; i < originalObjectsArray.length; i++)
{
delete originalObjectsArray[i].__obj_id;
};
return cloneObj;
}
一些快速测试
var auxobj = {
prop1 : "prop1 aux val",
prop2 : ["prop2 item1", "prop2 item2"]
};
var obj = new Object();
obj.prop1 = "prop1_value";
obj.prop2 = [auxobj, auxobj, "some extra val", undefined];
obj.nr = 3465;
obj.bool = true;
obj.f1 = function (){
this.prop1 = "prop1 val changed by f1";
};
objclone = clone(obj);
//some tests i've made
console.log("test number, boolean and string cloning: " + (objclone.prop1 == obj.prop1 && objclone.nr == obj.nr && objclone.bool == obj.bool));
objclone.f1();
console.log("test function cloning 1: " + (objclone.prop1 == 'prop1 val changed by f1'));
objclone.f1.prop = 'some prop';
console.log("test function cloning 2: " + (obj.f1.prop == undefined));
objclone.prop2[0].prop1 = "prop1 aux val NEW";
console.log("test multiple references cloning 1: " + (objclone.prop2[1].prop1 == objclone.prop2[0].prop1));
console.log("test multiple references cloning 2: " + (objclone.prop2[1].prop1 != obj.prop2[0].prop1));