It's hard to do a generic but useful clone operation because what should be cloned recursively and what should be just copied depends on how the specific object is supposed to work.
Something that may be useful is
function clone(x)
{
if (x === null || x === undefined)
return x;
if (typeof x.clone === "function")
return x.clone();
if (x.constructor == Array)
{
var r = [];
for (var i=0,n=x.length; i<n; i++)
r.push(clone(x[i]));
return r;
}
return x;
}
In this code the logic is
- in case of `null` or `undefined` just return the same (the special case is needed because it's an error to try to see if a `clone` method is present)
- does the object have a `clone` method ? then use that
- is the object an array ? then do a recursive cloning operation
- otherwise just return the same value
This clone function should allow implementing custom clone methods easily... for example
function Point(x, y)
{
this.x = x;
this.y = y;
...
}
Point.prototype.clone = function()
{
return new Point(this.x, this.y);
};
function Polygon(points, style)
{
this.points = points;
this.style = style;
...
}
Polygon.prototype.clone = function()
{
return new Polygon(clone(this.points),
this.style);
};
When in the object you know that a correct cloning operation for a specific array is just a shallow copy then you can call `values.slice()` instead of `clone(values)`.
For example in the above code I am explicitly requiring that a cloning of a polygon object will clone the points, but will share the same style object. If I want to clone the style object too instead then I can just pass `clone(this.style)`.