Javascript cloning objects
Thursday, 10 April 2008
I haven’t posted for a while as I’ve been busy but I thought I’d post about object cloning because it’s a useful tip and can be used in many situations like browser hacking or general web development. I posted this to the sla.ckers forum a while ago but in case you missed it here goes….
When cloning a object in Javascript many of the examples I found used for(i in..) to traverse the properties and copy each of them. There is a nicer way to do this using the uneval function like this:-
obj={a:1,a:2}
function clone(o) {
return eval(uneval(o));
}
obj2 = clone(obj);
obj2.a=0;
alert(obj.a);
alert(obj2.a);
Giorgio Maone pointed out that it would be nice to prototype the code to make it easier to implement:-
Object.prototype.clone = function() {
return eval(uneval(this));
}
alert("test".clone());
alert((3).clone());
alert(clone.clone());
No. 1 — April 10th, 2008 at 9:54 am
Hi Gareth,
Great tips! Unfortunately, if the object contains a reference to an HTML or XML element, those references is not cloned (of course). Which in turn makes this solution a little inadequate.
Yet, thanx for the trick!
No. 2 — April 10th, 2008 at 11:05 am
of course that works with FF and a few other browsers only. The more universal way of doing the same is exactly what I used in CoreAPI: http://www.gnucitizen.org/projects/coreapi/
CoreAPI.clone = function (o) {
function c(o) {
for (var i in o) {
this[i] = o[i];
}
}
return new c(o);
};
No. 3 — April 10th, 2008 at 12:43 pm
@pdp
Damn I thought it worked in IE7 ah well neat trick anyways
No. 4 — April 10th, 2008 at 5:08 pm
It is bad practice to mingle with Object.prototype because it messes up property enumeration. Just google “Object.prototype is verboten” and a zillion arguments will appear. The Prototype JavaScript library once did this in 1.3 – with bad results.
The fix is to instead tack methods on to the global Object. For example:
Object.clone = function(object) { return eval(uneval(object)); };
No. 5 — April 10th, 2008 at 5:19 pm
@kourge
Nice tip and good point
No. 6 — April 20th, 2008 at 6:38 pm
Have you not about c & c++ ‘s book ?
Post my E-mail,thank you
No. 7 — May 9th, 2008 at 5:29 pm
Your eval/uneval idea inspired me a cross-browser solution for those using YUI:
function clone = function( obj ) {
return YAHOO.lang.JSON.parse( YAHOO.lang.JSON.stringify( obj ) );
}
Tested fine with IE6 and FF2. Especially convenient for cloning arrays, hashs of arrays, arrays of hashs, etc.
Not sure about the performances. Might slow down your app if used to massively clone objects…
No. 8 — February 18th, 2009 at 1:20 pm
eval(uneval())
does not work for me
No. 9 — February 18th, 2009 at 3:26 pm
@alex
It’s Firefox only
No. 10 — March 5th, 2009 at 10:06 am
The following function is a variant on Mikael Grave’s browser independent solution with the JSON library:
No. 11 — July 6th, 2009 at 9:25 am
Nice approach.
Unfortunately it works only in Firefox (breaks in Chrome, Safari and IE). Therefore useless for production use (unless you can restrict access to Firefox users only)…
No. 12 — September 8th, 2009 at 8:26 pm
Another implementation that worked for me.
var originalJSONObj = this.jsonPanelData.fieldList; //fieldList is the json object being passed from server side
var clonedJSONObj = this.deepCloneJSON(originalJSONObj); //clonedJSONObj is the cloned object
deepCloneJSON: function(obj) {
var outpurArr = new Array();
for (var i in obj) {
outpurArr[i] = typeof (obj[i]) == ‘object’ ? this.deepCloneJSON(obj[i]) : obj[i];
}
return outpurArr;
},
No. 13 — May 24th, 2010 at 1:07 am
So, this is nice for FF, but in Opera 10.50 still doesn’t work.
But thanks to Praveen I have such idea for Opera:
function clone(o) {
return eval(‘(‘ + JSON.stringify(o) + ‘)’);
}
No. 14 — May 27th, 2010 at 1:59 pm
@Tipsy Snake
That also works in IE8 🙂