我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
当前回答
我认为有一个简单有效的答案。在深度复制中,有两个问题:
保持财产相互独立。并在克隆的对象上保持方法的有效性。
所以我认为一个简单的解决方案是首先序列化和反序列化,然后对其进行赋值以复制函数。
let deepCloned = JSON.parse(JSON.stringify(source));
let merged = Object.assign({}, source);
Object.assign(merged, deepCloned);
虽然这个问题有很多答案,但我希望这个问题也能有所帮助。
其他回答
//
// creates 'clone' method on context object
//
// var
// clon = Object.clone( anyValue );
//
!((function (propertyName, definition) {
this[propertyName] = definition();
}).call(
Object,
"clone",
function () {
function isfn(fn) {
return typeof fn === "function";
}
function isobj(o) {
return o === Object(o);
}
function isarray(o) {
return Object.prototype.toString.call(o) === "[object Array]";
}
function fnclon(fn) {
return function () {
fn.apply(this, arguments);
};
}
function owns(obj, p) {
return obj.hasOwnProperty(p);
}
function isemptyobj(obj) {
for (var p in obj) {
return false;
}
return true;
}
function isObject(o) {
return Object.prototype.toString.call(o) === "[object Object]";
}
return function (input) {
if (isfn(input)) {
return fnclon(input);
} else if (isobj(input)) {
var cloned = {};
for (var p in input) {
owns(Object.prototype, p)
|| (
isfn(input[p])
&& ( cloned[p] = function () { return input[p].apply(input, arguments); } )
|| ( cloned[p] = input[p] )
);
}
if (isarray(input)) {
cloned.length = input.length;
"concat every filter forEach indexOf join lastIndexOf map pop push reduce reduceRight reverse shift slice some sort splice toLocaleString toString unshift"
.split(" ")
.forEach(
function (methodName) {
isfn( Array.prototype[methodName] )
&& (
cloned[methodName] =
function () {
return Array.prototype[methodName].apply(cloned, arguments);
}
);
}
);
}
return isemptyobj(cloned)
? (
isObject(input)
? cloned
: input
)
: cloned;
} else {
return input;
}
};
}
));
//
有很多答案,但没有一个提到ECMAScript 5中的Object.create,它确实没有给您一个确切的副本,而是将源设置为新对象的原型。
因此,这不是问题的确切答案,但它是一个单行解决方案,因此很优雅。它最适合2种情况:
在这种继承有用的地方(duh!)源对象不会被修改,因此这两个对象之间的关系不成问题。
例子:
var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - prototype changed
bar.a = 3;
foo.a; // Still 2, since setting bar.a makes it an "own" property
为什么我认为这种解决方案更优越?它是本地的,因此没有循环,没有递归。然而,较旧的浏览器将需要polyfill。
对克隆简单对象感兴趣:
JSON.parse(JSON.stringify(JSON_inoriginal));
来源:如何通过引用将JavaScript对象复制到新变量NOT?
您可以克隆一个对象,并使用一行代码从上一个对象中删除任何引用。只需执行以下操作:
var obj1 = { text: 'moo1' };
var obj2 = Object.create(obj1); // Creates a new clone without references
obj2.text = 'moo2'; // Only updates obj2's text property
console.log(obj1, obj2); // Outputs: obj1: {text:'moo1'}, obj2: {text:'moo2'}
对于当前不支持Object.create的浏览器/引擎,可以使用以下polyfill:
// Polyfill Object.create if it does not exist
if (!Object.create) {
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
}
对于使用AngularJS的用户,也可以直接克隆或扩展此库中的对象。
var destination = angular.copy(source);
or
angular.copy(source, destination);
更多关于angular.copy文档。。。