-
-
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.