-
-
Save valueof/6033987 to your computer and use it in GitHub Desktop.
// Candidate 1 | |
JSON.parse(JSON.stringify(obj)); | |
// Candidate 2 | |
var desc = {}; | |
Object.keys(obj).forEach(function(key) { | |
desc[key] = Object.getOwnPropertyDescriptor(obj, key); | |
}); | |
Object.create(Object.prototype, desc); |
Methods/functions are not clonable by any reliable means, especially since you couldn't re-create the closure they'd have, so that's a non-point.
Do developers mean by "object clone" that they want a deep clone? Maybe. Maybe not. But deep cloning is deeply troublesome. Setting aside functions, what do you do about self-references or circular references? What about non-clonable objects like special built-in host objects, window
, DOM elements, etc? I think Object deep cloning is undefinable. Object shallow cloning (copying primitives, preserving references) is somewhat less troublesome, but still has issues with circular references and self-references.
OTOH, JSON cloning is quite well defined. So, I personally just punt on the whole "object cloning" thing, and only do JSON cloning. I just make it into a JSON.clone()
"hopefill":
if (!JSON.clone) {
JSON.clone = function(o) { return JSON.parse(JSON.stringify(o)); };
}
As @simevidas said: candidate 1 discards all non-JSON values.
For candidate 2, I’d use Object.getOwnPropertyNames()
instead of Object.keys()
. As @getify mentioned, you’ll have problems whenever a property contains a mutable value (such as an array). If you are working with your own objects, a different technique may be better. For example: a copy constructor, a constructor that initializes the current instance via another instance. Lastly, line 9 should be:
Object.create(Object.getPrototypeOf(obj), desc);
If you are after speed, the following variation of candidate 2 may be faster (maybe with a normal for
loop instead of foreach
):
var clone = Object.create(Object.getPrototypeOf(obj));
Object.getOwnPropertyNames(obj).forEach(function (key) {
Object.defineProperty(clone, key, Object.getOwnPropertyDescriptor(obj, key));
});
Candidate 1 has limitations. Methods are not cloned, and the inheritance chain of the original is discarded.
Line 9 should be
desc = Object.create(…
, I think.