Cloning an Object

JavaScript performance comparison

Revision 8 of this test case created

Info

There is no quick and easy facility for cloning an object, Some people recommend using JQuery.extend others JSON.parse/stringify

http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object

If you want the fastest possible clone function. I would personally anticipate the data structure of your object and write a custom clone to handle it.

Preparation code

<script src="http://code.jquery.com/jquery-1.5.1.js" type="text/javascript"></script>

<script src="http://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
<script>
  var oldObject = {
   a: 1,
   b: 2,
   c: 3,
   d: 4,
   e: 5,
   f: function() {
    return 6;
   },
   g: [7, 8, 9],
   h: function () { return true; },
   i: { a: function () { return true; } }
  };
 
 
  function clone(obj) {
   var target = {};
   for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
     target[i] = obj[i];
    }
   }
   return target;
  }
 
  function clone2(o) {
      var a;
      if (Date.isInstanceOfType(o)) {
          return new Date((o).getTime());
      }
      else if (Array.isInstanceOfType(o)) {
          a = [];
      }
      else if (Function.isInstanceOfType(o)) {
          return o;
      }
      else if (Object.isInstanceOfType(o)) {
          a = {};
      }
      else {
          return o;
      }
      for (var i in o) {
          if (o.hasOwnProperty(i)) {
              a[i] = clone2(o[i]);
          }
      }
      return a;
  }
 
  function cloneJsonObject(o) {
  // similar to clone2, but assuming o came from a JSON string, so we can skip hasOwnProperty checks
      var a;
      if (Date.isInstanceOfType(o)) {
          return new Date((o).getTime());
      }
      else if (Array.isInstanceOfType(o)) {
          a = [];
      }
      else if (Function.isInstanceOfType(o)) {
          return o;
      }
      else if (Object.isInstanceOfType(o)) {
          a = {};
      }
      else {
          return o;
      }
      for (var i in o) {
          a[i] = cloneJsonObject(o[i]);
      }
      return a;
  }
 
  Object.defineProperties(Object, {
   'extend': {
    'configurable': true,
    'enumerable': false,
    'value': function extend(what, wit) {
     var extObj, witKeys = Object.keys(wit);
 
     extObj = Object.keys(what).length ? Object.clone(what) : {};
 
     witKeys.forEach(function(key) {
      Object.defineProperty(extObj, key, Object.getOwnPropertyDescriptor(wit, key));
     });
 
     return extObj;
    },
    'writable': true
   },
   'clone': {
    'configurable': true,
    'enumerable': false,
    'value': function clone(obj) {
     return Object.extend({}, obj);
    },
    'writable': true
   }
  });
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
JQuery.extend deep
var newObject = jQuery.extend(true, {}, oldObject);
pending…
JSON
var newObject = JSON.parse(JSON.stringify(oldObject));
pending…
JQuery.extend
var newObject = jQuery.extend({}, oldObject);
pending…
simple clone function
var newObject = clone(oldObject);
pending…
ES5 Object.clone
var newObject = Object.create(oldObject);
pending…
MSAjax
// This properly clones dates, but it is slow
var newObject = Sys.Serialization.JavaScriptSerializer.deserialize(Sys.Serialization.JavaScriptSerializer.serialize(oldObject));
pending…
Properly clone dates
// This properly clones dates and is faster than serializing
var newObject = clone2(oldObject);
pending…
cloneJsonObject
// Similar to the above, but assumes all properties in the object must be cloned, therefore skips the hasOwnProperty check.
var newObject = cloneJsonObject(oldObject);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment