我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
当前回答
A.Levy的答案几乎是完整的,这是我的一点贡献:有一种方法可以处理递归引用,请看下面这行
如果(this[attr]==this)copy[attr]=复制;
如果对象是XMLDOM元素,则必须改用cloneNode
if(this.cloneNode)返回this.clone节点(true);
受A.Levy的详尽研究和Calvin的原型设计方法启发,我提供了以下解决方案:
Object.prototype.clone = function() {
if(this.cloneNode) return this.cloneNode(true);
var copy = this instanceof Array ? [] : {};
for(var attr in this) {
if(typeof this[attr] == "function" || this[attr]==null || !this[attr].clone)
copy[attr] = this[attr];
else if(this[attr]==this) copy[attr] = copy;
else copy[attr] = this[attr].clone();
}
return copy;
}
Date.prototype.clone = function() {
var copy = new Date();
copy.setTime(this.getTime());
return copy;
}
Number.prototype.clone =
Boolean.prototype.clone =
String.prototype.clone = function() {
return this;
}
另请参见答案中的Andy Burke注释。
其他回答
根据Apple JavaScript编码指南:
// Create an inner object with a variable x whose default
// value is 3.
function innerObj()
{
this.x = 3;
}
innerObj.prototype.clone = function() {
var temp = new innerObj();
for (myvar in this) {
// this object does not contain any objects, so
// use the lightweight copy code.
temp[myvar] = this[myvar];
}
return temp;
}
// Create an outer object with a variable y whose default
// value is 77.
function outerObj()
{
// The outer object contains an inner object. Allocate it here.
this.inner = new innerObj();
this.y = 77;
}
outerObj.prototype.clone = function() {
var temp = new outerObj();
for (myvar in this) {
if (this[myvar].clone) {
// This variable contains an object with a
// clone operator. Call it to create a copy.
temp[myvar] = this[myvar].clone();
} else {
// This variable contains a scalar value,
// a string value, or an object with no
// clone function. Assign it directly.
temp[myvar] = this[myvar];
}
}
return temp;
}
// Allocate an outer object and assign non-default values to variables in
// both the outer and inner objects.
outer = new outerObj;
outer.inner.x = 4;
outer.y = 16;
// Clone the outer object (which, in turn, clones the inner object).
newouter = outer.clone();
// Verify that both values were copied.
alert('inner x is '+newouter.inner.x); // prints 4
alert('y is '+newouter.y); // prints 16
史蒂夫
如果您的对象是类(例如。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes):
var copiedObject = jQuery.extend(true, {}, originalObject);
copiedObject.__proto__ = originalObject.__proto__;
然后在copiedObject中,您有一个originalObject类及其所有方法的深度复制实例。
使用默认值(历史上特定于nodejs,但由于现代JS,现在可以从浏览器中使用):
import defaults from 'object.defaults';
const myCopy = defaults({}, myObject);
使用lodash_.cloneDeep()。
浅拷贝:lodash_.clone()
只需复制参考即可进行浅层复制。
let obj1 = {
a: 0,
b: {
c: 0,
e: {
f: 0
}
}
};
let obj3 = _.clone(obj1);
obj1.a = 4;
obj1.b.c = 4;
obj1.b.e.f = 100;
console.log(JSON.stringify(obj1));
//{"a":4,"b":{"c":4,"e":{"f":100}}}
console.log(JSON.stringify(obj3));
//{"a":0,"b":{"c":4,"e":{"f":100}}}
深度复制:lodash_.cloneDeep()
取消引用字段:而不是复制对象的引用
let obj1 = {
a: 0,
b: {
c: 0,
e: {
f: 0
}
}
};
let obj3 = _.cloneDeep(obj1);
obj1.a = 100;
obj1.b.c = 100;
obj1.b.e.f = 100;
console.log(JSON.stringify(obj1));
{"a":100,"b":{"c":100,"e":{"f":100}}}
console.log(JSON.stringify(obj3));
{"a":0,"b":{"c":0,"e":{"f":0}}}
如果对象中没有循环依赖关系,我建议使用其他答案之一或jQuery的复制方法,因为它们看起来都很有效。
如果存在循环依赖关系(即,两个子对象彼此链接),那么你就有点糟糕了,因为(从理论角度)没有办法优雅地解决这个问题。