Reputation: 135
I have a Class Persons
that contains an array of Person
and functions :
function Persons() {
this.mItems = []; // Array of Objects Person
}
Persons.prototype = {
calculateScores : function() {
// Do some stuff
}
}
The Class Person
has members and functions :
function Person(name) {
this.name = name; // Name of the Person
this.score = 0;
}
Person.prototype = {
calculateScore : function() {
// Do some stuff
}
}
I want that the program does the following things :
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
I want to deep copy an instance of Persons
to completely duplicate the Array of Person
. The Objects Person must be duplicated. The functions of the Objects must be kept.
JQuery.extend(true, {}, persons)
clones the direct members of Persons
but shallow copies the Person
Objects.
console.log(persons.mItems[0].name); // Mick : Where is John ?!
console.log(clonedPersons.mItems[0].name); // Mick
clonedPersons = JSON.parse(json.stringify(persons))
clones the Objects but remove the functions.
persons.mItems[0].calculateScore(); // Does not exists !!!
Thank you for your answers.
Upvotes: 2
Views: 1536
Reputation: 55678
If you're dealing with custom classes, you're going to want to implement custom clone
methods. Generally, in this context, I'd have 2 separate clone
functions, one on the Person
model and one on the Persons
collection.
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;
}
}
The advantage to this approach is that it separates the concerns - the Person
class doesn't have to know how to clone a single Person
, it only has to know that Person
exposes a clone
method. If Person
adds a new property that should be persisted in the clone, only Person
needs to change.
It's generally an anti-pattern to use generic clone
methods, e.g. from jQuery or Underscore, in this context. They'll end up cloning things you don't want, or missing things you do (e.g. a Person
might eventually have an Address
or some other object that will also need cloning).
Upvotes: 3
Reputation: 288710
You can use [].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;
};
Upvotes: 0