如何深度复制(克隆)Javascript中包含数组成员的对象?
How to deep copy (clone) an object with array members in Javascript?
简介
我有一个 Class Persons
,其中包含一个 Person
数组和函数:
function Persons() {
this.mItems = []; // Array of Objects Person
}
Persons.prototype = {
calculateScores : function() {
// Do some stuff
}
}
Class Person
有成员和函数:
function Person(name) {
this.name = name; // Name of the Person
this.score = 0;
}
Person.prototype = {
calculateScore : function() {
// Do some stuff
}
}
我希望该程序执行以下操作:
var persons = new Persons();
var person0 = new Person("John");
var person1 = new Person("Sam");
persons.mItems.push(person0);
persons.mItems.push(person1);
// Completely clone the original Objects
clonedPersons = persons.clone(); // I am looking for a clone() function
// Modify an item in the cloned Objects
clonedPersons.mItems[0].name = "Mick";
// Check that the original Objects have not been modified
console.log(persons.mItems[0].name); // John : Not modified
console.log(clonedPersons.mItems[0].name); // Mick
问题
我想深度复制 Persons
的实例以完全复制 Person
的数组。 Objects Person 必须复制。必须保留对象的功能。
JQuery.extend()
JQuery.extend(true, {}, persons)
克隆 Persons
的直接成员,但浅拷贝 Person
对象。
console.log(persons.mItems[0].name); // Mick : Where is John ?!
console.log(clonedPersons.mItems[0].name); // Mick
JSON.parse(json.stringify())
clonedPersons = JSON.parse(json.stringify(persons))
克隆对象但删除函数。
persons.mItems[0].calculateScore(); // Does not exists !!!
感谢您的回答。
您可以使用 [].map
and Object.assign
:
Persons.prototype.clone = function() {
var clone = new Persons();
clone.mItems = this.mItems.map(function(person) {
return Object.assign(new Person, person);
});
return clone;
};
如果您正在处理自定义 classes,您将需要实现自定义 clone
方法。一般来说,在这种情况下,我会有 2 个单独的 clone
函数,一个在 Person
模型上,一个在 Persons
集合上。
Persons.prototype = {
clone: function() {
var clone = new Persons();
clone.mItems = this.mItems.map(function(person) {
return person.clone();
});
return clone;
}
}
Person.prototype = {
clone: function() {
var clone = new Person(this.name);
clone.score = this.score;
return clone;
}
}
这种方法的优点是它分离了关注点 - Person
class 不必知道如何克隆单个 Person
,它只需要知道Person
公开了一个 clone
方法。如果 Person
添加了一个新的 属性 应该保留在克隆中,只有 Person
需要改变。
使用通用 clone
方法通常是一种反模式,例如来自 jQuery 或下划线,在此上下文中。他们最终会克隆你不想要的东西,或者丢失你做的东西(例如 Person
最终可能有一个 Address
或其他一些也需要克隆的对象)。
简介
我有一个 Class Persons
,其中包含一个 Person
数组和函数:
function Persons() {
this.mItems = []; // Array of Objects Person
}
Persons.prototype = {
calculateScores : function() {
// Do some stuff
}
}
Class Person
有成员和函数:
function Person(name) {
this.name = name; // Name of the Person
this.score = 0;
}
Person.prototype = {
calculateScore : function() {
// Do some stuff
}
}
我希望该程序执行以下操作:
var persons = new Persons();
var person0 = new Person("John");
var person1 = new Person("Sam");
persons.mItems.push(person0);
persons.mItems.push(person1);
// Completely clone the original Objects
clonedPersons = persons.clone(); // I am looking for a clone() function
// Modify an item in the cloned Objects
clonedPersons.mItems[0].name = "Mick";
// Check that the original Objects have not been modified
console.log(persons.mItems[0].name); // John : Not modified
console.log(clonedPersons.mItems[0].name); // Mick
问题
我想深度复制 Persons
的实例以完全复制 Person
的数组。 Objects Person 必须复制。必须保留对象的功能。
JQuery.extend()
JQuery.extend(true, {}, persons)
克隆 Persons
的直接成员,但浅拷贝 Person
对象。
console.log(persons.mItems[0].name); // Mick : Where is John ?!
console.log(clonedPersons.mItems[0].name); // Mick
JSON.parse(json.stringify())
clonedPersons = JSON.parse(json.stringify(persons))
克隆对象但删除函数。
persons.mItems[0].calculateScore(); // Does not exists !!!
感谢您的回答。
您可以使用 [].map
and Object.assign
:
Persons.prototype.clone = function() {
var clone = new Persons();
clone.mItems = this.mItems.map(function(person) {
return Object.assign(new Person, person);
});
return clone;
};
如果您正在处理自定义 classes,您将需要实现自定义 clone
方法。一般来说,在这种情况下,我会有 2 个单独的 clone
函数,一个在 Person
模型上,一个在 Persons
集合上。
Persons.prototype = {
clone: function() {
var clone = new Persons();
clone.mItems = this.mItems.map(function(person) {
return person.clone();
});
return clone;
}
}
Person.prototype = {
clone: function() {
var clone = new Person(this.name);
clone.score = this.score;
return clone;
}
}
这种方法的优点是它分离了关注点 - Person
class 不必知道如何克隆单个 Person
,它只需要知道Person
公开了一个 clone
方法。如果 Person
添加了一个新的 属性 应该保留在克隆中,只有 Person
需要改变。
使用通用 clone
方法通常是一种反模式,例如来自 jQuery 或下划线,在此上下文中。他们最终会克隆你不想要的东西,或者丢失你做的东西(例如 Person
最终可能有一个 Address
或其他一些也需要克隆的对象)。