Cloning an Object (v86)

Revision 86 of this benchmark created on


Description

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 HTML

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


<script>
  var oldObject = {
   a: 1,
   b: 2,
   c: 3,
   d: 4,
   e: 5,
   f: function() {
    return 6;
   },
   g: [7, 8, 9]
  };
  
  
  function clone(obj) {
   var target = {};
   for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
     target[i] = obj[i];
    }
   }
   return target;
  }
  
  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
   }
  });

//Crockford clone function
function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

// Nodejs util _extend
function nodeextend (origin, add) {
  // Don't do anything if add isn't an object
  if (!add || typeof add !== 'object') return origin;

  var keys = Object.keys(add);
  var i = keys.length;
  while (i--) {
    origin[keys[i]] = add[keys[i]];
  }
  return origin;
};


function recursive(obj){
    if(obj == null || typeof(obj) != 'object')
        return obj;

    var temp = obj.constructor(); // changed

    for(var key in obj)
        temp[key] = recursive(obj[key]);
    return temp;
}

function deepObjCopy (dupeObj) {
        var retObj = new Object();
        if (dupeObj != null && typeof(dupeObj) == 'object') {
                if (typeof(dupeObj.length) != 'undefined')
                        var retObj = new Array();
                for (var objInd in dupeObj) {
                        if (typeof(dupeObj[objInd]) == 'object') {
                                retObj[objInd] = deepObjCopy(dupeObj[objInd]);
                        } else if (typeof(dupeObj[objInd]) == 'string') {
                                retObj[objInd] = dupeObj[objInd];
                        } else if (typeof(dupeObj[objInd]) == 'number') {
                                retObj[objInd] = dupeObj[objInd];
                        } else if (typeof(dupeObj[objInd]) == 'boolean') {
                                ((dupeObj[objInd] == true) ? retObj[objInd] = true : retObj[objInd] = false);
                        }
                }
        }
        return retObj;
}
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
JQuery.extend deep
var newObject = jQuery.extend(true, {}, oldObject);
ready
JSON
var newObject = JSON.parse(JSON.stringify(oldObject));
ready
JQuery.extend
var newObject = jQuery.extend({}, oldObject);
ready
simple clone function
var newObject = clone(oldObject);
ready
ES5 Object.clone
var newObject = Object.clone(oldObject);
ready
Crockford Clone Function
var newObject = object(oldObject);
ready
    var newObject = {};
    for (var k in oldObject){
    newObject[k]=oldObject[k];   
    }
 
ready
Nodejs require('util')._extend
var newObject = nodeextend({}, oldObject);
ready
recursive
var newObject = recursive(oldObject);
ready
deepObjCopy
var newObject = deepObjCopy(oldObject);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.