From 4a0537223b65cc001cefe37309f8c6cf94d80ac3 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 5 Apr 2011 23:38:13 -0400 Subject: [PATCH] Added deep copy to util.copyTo() --- lib/util.js | 29 +++++++++++++++++++++-------- test/test-util-copy.js | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lib/util.js b/lib/util.js index 003144a..148674e 100644 --- a/lib/util.js +++ b/lib/util.js @@ -178,13 +178,18 @@ exports.clone = function clone( data, deep ) * destination argument is first to allow extending an object without using the * full-blown class system. * - * @param {Object} dest destination object - * @param {Object} src source object + * If a deep copy is not performed, all values will be copied by reference. + * + * @param {Object} dest destination object + * @param {Object} src source object + * @param {boolean} deep perform deep copy (slower) * * @return {Object} dest */ -exports.copyTo = function( dest, src ) +exports.copyTo = function( dest, src, deep ) { + deep = !!deep; + var get, set, data; // sanity check @@ -204,14 +209,18 @@ exports.copyTo = function( dest, src ) if ( data.get || data.set ) { - // define the property the slower way (only needed for - // getters/setters) + // Define the property the slower way (only needed for + // getters/setters). We don't have to worry about cloning in + // this case, since getters/setters are methods. Object.defineProperty( dest, prop, data ); } else { - // normal copy by reference - dest[ prop ] = src[ prop ]; + // normal copy; cloned if deep, otherwise by reference + dest[ prop ] = ( deep ) + ? exports.clone( src[ prop ], true ) + : src[ prop ] + ; } } } @@ -220,7 +229,11 @@ exports.copyTo = function( dest, src ) { for ( prop in src ) { - dest[ prop ] = src[ prop ]; + // normal copy; cloned if deep, otherwise by reference + dest[ prop ] = ( deep ) + ? exports.clone( src[ prop ], true ) + : src[ prop ] + ; } } diff --git a/test/test-util-copy.js b/test/test-util-copy.js index 2ed1b4c..2e76f09 100644 --- a/test/test-util-copy.js +++ b/test/test-util-copy.js @@ -142,3 +142,24 @@ var common = require( './common' ), }, TypeError, "Src parameter is required to be an object" ); } )(); + +/** + * For convenience, let's support a deep copy as well, just in case they don't + * want to copy everything by reference. + */ +( function testCanDeepCopy() +{ + var src = { foo: [ 1, 2, 3 ] }, + dest = copyTo( {}, src, true ); + + // copied values should be equal by value... + assert.deepEqual( src.val, dest.val, + "Copied values should be comparitively equal with deep copy" + ); + + // ...but not by reference + assert.ok( src.foo !== dest.foo, + "Copied values should not be the same object after deep copy" + ); +} )(); +