Clone Anything with JavaScript

One topic or concept that causes confusion when developers start with JavaScript is the idea of passing objects by reference; for example, setting two variables equal to the same object actually creates a reference to that same object. Sending an object to a function and modify that argument within the function actually modifies the original object. Sometimes we'd prefer to send around a clone of something, a date, array, or maybe an object literal. The Dojo Toolkit provides an excellent method for cloning just about anything. Even better is that the functionality is easy to pull out of Dojo for your own toolkit.

The JavaScript

The clone method will deep clone nodes, object literals, arrays, dates, regular expressions, and generic objects:

function clone(src) { function mixin(dest, source, copyFunc) { var name, s, i, empty = {}; for(name in source){ // the (!(name in empty) || empty[name] !== s) condition avoids copying properties in "source" // inherited from Object.prototype. For example, if dest has a custom toString() method, // don't overwrite it with the toString() method that source inherited from Object.prototype s = source[name]; if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){ dest[name] = copyFunc ? copyFunc(s) : s; } } return dest; } if(!src || typeof src != "object" || Object.prototype.toString.call(src) === "[object Function]"){ // null, undefined, any non-object, or function return src; // anything } if(src.nodeType && "cloneNode" in src){ // DOM Node return src.cloneNode(true); // Node } if(src instanceof Date){ // Date return new Date(src.getTime()); // Date } if(src instanceof RegExp){ // RegExp return new RegExp(src); // RegExp } var r, i, l; if(src instanceof Array){ // array r = []; for(i = 0, l = src.length; i < l; ++i){ if(i in src){ r.push(clone(src[i])); } } // we don't clone functions for performance reasons // }else if(d.isFunction(src)){ // // function // r = function(){ return src.apply(this, arguments); }; }else{ // generic objects r = src.constructor ? new src.constructor() : {}; } return mixin(r, src, clone); }

The code provided by Dojo also has the ability to clone functions, but that ability is disabled for performance reasons. I've placed the mixin function within clone itself, but that can also be defined at the same level and you can use mixin as a general function for merging objects. This method, of course, is just one of a thousand helpful snippets you can find within the Dojo Toolkit!