Last active
August 29, 2015 14:12
-
-
Save stevenschobert/76100e9f8519ad138742 to your computer and use it in GitHub Desktop.
Object Cloning (with deep support) - modeled after Lodash's _.clone implementation. Supports strings, numbers, booleans, dates, regexps, objects, and arrays.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function clone(value, deep) { | |
var boo = '[object Boolean]'; | |
var num = '[object Number]'; | |
var str = '[object String]'; | |
var obj = '[object Object]'; | |
var arr = '[object Array]'; | |
var date = '[object Date]'; | |
var reg = '[object RegExp]'; | |
var cloned; | |
var klass; | |
if (typeof value != 'object') { | |
return value; | |
} | |
klass = Object.prototype.toString.call(value); | |
switch (klass) { | |
case reg: | |
cloned = new value.constructor(value.source, /\w*$/.exec(value)); | |
cloned.lastIndex = value.lastIndex; | |
break; | |
case boo: | |
case date: | |
cloned = new value.constructor(+value); | |
break; | |
case num: | |
case str: | |
cloned = new value.constructor(value); | |
break; | |
case arr: | |
cloned = new value.constructor(); | |
for(var i=0; i < value.length; i++) { | |
if (deep) { | |
cloned.push(clone(value[i], deep)); | |
} else { | |
cloned.push(value[i]); | |
} | |
} | |
break; | |
case obj: | |
cloned = new value.constructor(); | |
for (var key in value) { | |
if (value.hasOwnProperty(key)) { | |
if (deep) { | |
cloned[key] = clone(value[key], deep); | |
} else { | |
cloned[key] = value[key]; | |
} | |
} | |
} | |
break; | |
default: | |
cloned = value; | |
break; | |
} | |
return cloned; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('#clone', function() { | |
it('should return values for booleans', function() { | |
assert.equal(clone(true), true); | |
assert.equal(typeof clone(true), 'boolean'); | |
}); | |
it('should return values for numbers', function() { | |
assert.equal(clone(2), 2); | |
assert.equal(typeof clone(2), 'number'); | |
}); | |
it('should return values for strings', function() { | |
assert.equal(clone('test'), 'test'); | |
assert.equal(typeof clone('test'), 'string'); | |
}); | |
it('should copy boolean objects', function() { | |
/* jshint -W053 */ | |
var bool = new Boolean(true); | |
assert.notEqual(bool, clone(bool)); | |
assert.equal(bool.valueOf(), clone(bool).valueOf()); | |
}); | |
it('should copy string objects', function() { | |
/* jshint -W053 */ | |
var testStr = new String('test'); | |
assert.notEqual(testStr, clone(testStr)); | |
assert.equal(testStr.valueOf(), clone(testStr).valueOf()); | |
}); | |
it('should copy number objects', function() { | |
/* jshint -W053 */ | |
var testNum = new Number(2); | |
assert.notEqual(testNum, clone(testNum)); | |
assert.equal(testNum.valueOf(), clone(testNum).valueOf()); | |
}); | |
it('should copy regexp objects', function() { | |
var testRegex = new RegExp('hello.*', 'i'); | |
var cloned = clone(testRegex); | |
assert.notEqual(testRegex, cloned); | |
assert.equal(testRegex.toString(), cloned.toString()); | |
}); | |
it('should copy date objects', function() { | |
var testDate = new Date(); | |
var cloned = clone(testDate); | |
assert.notEqual(testDate, cloned); | |
assert.equal(testDate.toString(), cloned.toString()); | |
}); | |
it('should copy custom objects', function() { | |
function Droid(model) { this.model = model; } | |
var c3po = new Droid('protocol'); | |
var cloned = clone(c3po); | |
assert.notEqual(cloned, c3po); | |
assert.deepEqual(cloned, c3po); | |
assert(cloned instanceof Droid); | |
}); | |
it('should copy object keys', function() { | |
var testObj = { one: 1, two: 'two' }; | |
assert.notEqual(clone(testObj), testObj); | |
assert.deepEqual(clone(testObj), testObj); | |
}); | |
it('should copy objects with deep copying', function() { | |
var testObj1 = { test: 'test' }; | |
var testObj2 = { one: testObj1 }; | |
var cloned = clone(testObj2, true); | |
assert.notEqual(cloned.one, testObj1); | |
assert.deepEqual(cloned.one, testObj1); | |
}); | |
it('should copy array values', function() { | |
var testArr = [ 'one', 2 ]; | |
assert.notEqual(clone(testArr), testArr); | |
assert.deepEqual(clone(testArr), testArr); | |
}); | |
it('should copy array values with deep copying', function() { | |
var testObj1 = { test: 'test' }; | |
var testArr = [ testObj1, 2 ]; | |
var cloned = clone(testArr, true); | |
assert.notEqual(cloned[0], testObj1); | |
assert.deepEqual(cloned[0], testObj1); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment