Skip to content

Instantly share code, notes, and snippets.

@valueof
Created July 18, 2013 23:34
Show Gist options
  • Save valueof/6033987 to your computer and use it in GitHub Desktop.
Save valueof/6033987 to your computer and use it in GitHub Desktop.
Which approach to cloning objects is faster? (Assuming there are no circular references, get/set, etc.)
// 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);
@simevidas
Copy link

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.

@getify
Copy link

getify commented Jul 19, 2013

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)); };
}

@rauschma
Copy link

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));
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment