cloning an object (v29)

Revision 29 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="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Setup

var oldObject = {
      a: 1,
      b: 2,
      c: 3,
      d: 4,
      e: 5,
      f: function() {
        return 6;
      },
      g: [7, 8, 9],
      h: {
        a: 1,
        b: 2,
        c: 3
      }
    };
    
    function replicate(obj) {
      return {
        a: obj.a,
        b: obj.b,
        c: obj.c,
        d: obj.d,
        e: obj.e,
        f: obj.f,
        g: obj.g,
        h: obj.h
      };
    }
    
    function clone_keys(obj) {
      var target = {};
      var keys = Object.keys(obj)
      for (var i = 0; i < keys.length; i++) {
        var key = keys[i]
        if (obj.hasOwnProperty(key)) {
          target[key] = obj[key]
        }
      }
      return target;
    }
    
    function clone(obj) {
      var target = {};
      for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
          target[i] = obj[i];
        }
      }
      return target;
    }
    
    function deepClone(obj) {
      if (obj == null || typeof obj !== 'object') {
        return obj;
      }
      var target = obj.constructor();
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          target[key] = deepClone(obj[key]);
        }
      }
      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
      }
    });
    
    function evalKeys(o) {
      console.log(o);
      var keys = Object.keys(o);
      var assign = 'var newO = {';
      var first = true;
      for (var i = 0; i < keys.length; i++) {
        assign += (first ? '' : ',') + keys[i] + ':o.' + keys[i];
        first = false;
      }
      assign += '}';
      eval(assign);
      return newO;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
jQuery.extend() deep
var newObject = jQuery.extend(true, {}, oldObject);
ready
JSON stringify/parse
var newObject = JSON.parse(JSON.stringify(oldObject));
ready
jQuery.extend()
var newObject = jQuery.extend({}, oldObject);
ready
clone with Object.keys() function
var newObject = clone_keys(oldObject);
ready
ES5 Object.clone
var newObject = Object.clone(oldObject);
ready
stringify eval
var newObject = eval("(" + JSON.stringify(oldObject) + ")");
ready
replicate function
// Copies known, static object structure. Manual cloning
var newObject = replicate(oldObject);
ready
clone function
var newObject = clone(oldObject);
ready
deepClone function
var newObject = deepClone(oldObject);
ready
eval + keys
var newObject = evalKeys(oldObject)
ready
cloneNode
var newObject = oldObject.cloneNode(true);
ready

Revisions

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