Reputation: 180
I have a board class:
var board = new Board();
I want to make a clone of the board and run a movePiece
function on the new board:
var newBoard = board;
newBoard.movePiece('4a', '3b');
Since I am just assigning it, both board
and newBoard
will have the moved piece.
How can I clone board to create an exact copy called newBoard that I can move the piece on and the original board will stay the same?
I have tried a couple different methods, such as:
Object.assign({}, orig)
and
function clone(orig) {
let origProto = Object.getPrototypeOf(orig);
return Object.assign(Object.create(origProto), orig);
}
from http://www.2ality.com/2014/12/es6-oop.html
Upvotes: 4
Views: 1315
Reputation: 707148
The only way to make a reliable clone for an arbitrary object is to write a method on that object that takes one instance and creates a new instance from the properties of the original instance.
This is because there's no way for an outside agent to know exactly how to treat every instance variable (what needs to be assigned, what needs to be copied, etc...) and it's also possible to have private instance variables too. So, just write a new method that creates a new object and copies over relevant properties or a constructor that takes another object and does the same.
It is possible to have an object that one could just assign all the properties to a new instance (if all properties were primitives), but that is usually not the case so more intelligence needs to be applied as to how to best assign each property to the new clone. And, an object could have private instance variables (closure variables) that could have to be dealt with manually too from the within some other method.
Here's an example of a relatively simple object that just has an array in it that needs to be copied. This one supports creation of a clone either via the constructor or via a clone method:
function CallbackList(otherObj) {
// if another object is passed to the constructor, then initialize this
// new instance to be a copy
if (otherObj) {
// copy the array from the other instance
this.list = otherObj.list.slice(0);
} else {
// initalize empty list
this.list = [];
}
}
CallbackList.prototype = {
addListener: function(fn) {
this.list.push(fn);
},
removeListener: function(fn) {
for (var i = this.list.length - 1; i >= 0; i--) {
if (this.list[i] === fn) {
this.list.splice(i, 1);
}
}
},
fire: function(/* pass args here */) {
var args = Array.prototype.slice.call(arguments);
this.list.forEach(function(fn) {
fn.apply(null, args);
});
},
clone: function() {
return new CallbackList(this);
}
};
To understand why you need custom code that is built specifically for your object to create a clone, here are some of the things that could be in the instance data that you may have to treat in an object-specific way:
Upvotes: 6