Or this, Alpha123, one can use json2 with cycles to eliminate cyclic structures:
/**
* Serialize(obj : object);
* - Use this to JSON an object; AND preserve the data type.
**/
function Serialize(obj)
{
function Make(obj) {
var o = Assert.isArray(obj) ? [] : { zztype: obj.constructor.name };
for (var i in obj) {
if (Assert.is(obj[i], "object")) o[i] = Make(obj[i]);
else o[i] = obj[i];
}
return o;
}
if(Assert.is(obj, "object"))
return JSON.stringify(Make(obj));
else
return JSON.stringify(obj);
}
/**
* Deserialize(s : string);
* - Use this to parse a JSON object; AND restore the methods.
**/
function Deserialize(s)
{
function Make(o) {
var obj = [];
if (!Assert.isArray(o)) {
if (o.zztype in this) obj = new global[o.zztype]();
else {
Debug.log("Can't deserialize type: {?}", o.zztype, LIB_ERROR);
return;
}
}
for (var i in o) {
if (Assert.is(o[i], "object")) obj[i] = Make(o[i]);
else obj[i] = o[i];
}
if (!Assert.isArray(obj)) delete obj.zztype;
return obj;
}
return Make(JSON.parse(s));
}
/**
* DeepClone(obj : object);
* - generates a full, deep, and accurate copy of the object.
**/
function DeepClone(obj) {
return Deserialize(Serialize(obj));
}
But it's not going to be lightning fast. And really, all you need is a clone for the job. If it's a simple thing that needs cloning say a point = {x: 0, y: 0 }; then you don't need a huge, fancy copier. LordEnglish's solution is fine for bigger, nested objects, and mine if you want full instanceof support and method keeping.
It doesn't clone native Sphere objects though. I'll have to have it find and add their .clone() methods.
(edit - cleaned up tags ~neo)