Skip to content

Instantly share code, notes, and snippets.

@kxtxr
Created June 23, 2018 09:06
Show Gist options
  • Save kxtxr/26bf36e446c9db0a8bfb70321f27dc4c to your computer and use it in GitHub Desktop.
Save kxtxr/26bf36e446c9db0a8bfb70321f27dc4c to your computer and use it in GitHub Desktop.
Deep clone an object
/**
* @type {Function}
*/
var toString = Object.prototype.toString;
/**
* @description Clones an object using deep copy
*
* @param {Object} sourceObject Object to clone
* @returns {Object} Cloned object.
* @throws {Error}
*/
function deepClone(sourceObject) {
if (!sourceObject || typeof sourceObject != "object") {
// Any non-object (Boolean, String, Number), null, undefined, NaN
return sourceObject;
}
// Honor native/custom clone methods
if (sourceObject.clone && toString.call(sourceObject.clone) == "[object Function]") {
return sourceObject.clone(deep);
}
// Date
if (sourceObject instanceof Date) {
var clone = new Date();
clone.setTime(sourceObject.getTime());
return clone;
}
// Array
if (sourceObject instanceof Array) {
var clone = [];
for (var i = 0, len = sourceObject.length; i < len; i++) {
clone[i] = deepClone(sourceObject[i]);
}
return clone;
}
// RegExp
if (toString.call(sourceObject) == "[object RegExp]") {
return new RegExp(sourceObject);
}
// DOM elements
if (sourceObject.nodeType && toString.call(sourceObject.cloneNode) == "[object Function]") {
// Deep clone the node
return sourceObject.cloneNode(true);
}
if (sourceObject instanceof Object) {
var clone = {};
for (var key in sourceObject) {
if (sourceObject.hasOwnProperty(key)) clone[key] = deepClone(sourceObject[key]);
}
return clone;
}
throw new Error("Unable to clone this object.");
}
if (typeof module === 'object' && module.exports) {
module.exports = deepClone
}
/* global describe, it */
var assert = require('assert');
var deepClone = require('./deepClone');
describe('deepClone', function() {
var testObj;
var clonedObj;
before( function() {
testObj = {
a: 2,
b: {
c: "A Name",
d: function(param) {
return param
},
e: {
f: 4,
g: 67,
h: [2, 6, Number]
},
g: false
},
j: new Date(),
k: /^[0-9]/
};
});
beforeEach( function() {
clonedObj = deepClone(testObj);
});
it('should clone testObj', function() {
assert.deepEqual(testObj, clonedObj);
});
it('should not be \'equal\'', function() {
clonedObj.a = 3;
assert.notDeepEqual(testObj, clonedObj);
});
it('should not be \'equal\'', function() {
clonedObj.b.g = true;
assert.notDeepEqual(testObj, clonedObj);
});
it('should not be \'equal\'', function() {
clonedObj.b.e.h[0] = 1;
assert.notDeepEqual(testObj, clonedObj);
});
});
@kxtxr
Copy link
Author

kxtxr commented Jun 23, 2018

Usage

var deepClone = require('./js-clone/index.js');

var object = {
    name: 'Kator James',
    work: {
        companyName: 'LogicalAddress Ltd',
        getCompanyName: function() {
            // ...
        }
    }
}
var clone = deepClone(object);

Test

# To run unit tests
npm install --save-dev mocha
node_modules/mocha/bin/_mocha test.js
# To run test with coverage
npm install --save-dev mocha istanbul standard
istanbul cover node_modules/mocha/bin/_mocha test.js --bail

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