Add _.cloneDeep alias of _.clone(…, true). [closes #140]

Former-commit-id: b71397d5c5b71cb28a60eb4656cbaf12f6b03d1a
This commit is contained in:
John-David Dalton
2012-12-14 00:24:02 -08:00
parent b2af8da9a2
commit 90597530a4
5 changed files with 46 additions and 22 deletions

View File

@@ -71,6 +71,7 @@
'bindAll': ['bind', 'functions'], 'bindAll': ['bind', 'functions'],
'bindKey': ['isFunction', 'isObject'], 'bindKey': ['isFunction', 'isObject'],
'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'], 'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'],
'cloneDeep': ['clone'],
'compact': [], 'compact': [],
'compose': [], 'compose': [],
'contains': ['indexOf', 'isString'], 'contains': ['indexOf', 'isString'],
@@ -239,6 +240,7 @@
/** List of methods used by Underscore */ /** List of methods used by Underscore */
var underscoreMethods = _.without.apply(_, [allMethods].concat([ var underscoreMethods = _.without.apply(_, [allMethods].concat([
'bindKey', 'bindKey',
'cloneDeep',
'forIn', 'forIn',
'forOwn', 'forOwn',
'isPlainObject', 'isPlainObject',

View File

@@ -69,6 +69,7 @@
'bindAll', 'bindAll',
'bindKey', 'bindKey',
'clone', 'clone',
'cloneDeep',
'collect', 'collect',
'compact', 'compact',
'compose', 'compose',

View File

@@ -256,8 +256,8 @@
* `unshift`, `values`, `where`, `without`, `wrap`, and `zip` * `unshift`, `values`, `where`, `without`, `wrap`, and `zip`
* *
* The non-chainable wrapper functions are: * The non-chainable wrapper functions are:
* `clone`, `contains`, `escape`, `every`, `find`, `has`, `identity`, `indexOf`, * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`,
* `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`,
* `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`,
* `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`,
* `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`, * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`,
@@ -967,14 +967,8 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Creates a clone of `value`. If `deep` is `true`, all nested objects will * Creates a clone of `value`. If `deep` is `true`, nested objects will also
* also be cloned, otherwise they will be assigned by reference. Functions and * be cloned, otherwise they will be assigned by reference.
* DOM nodes are **not** cloned. The enumerable properties of `arguments` objects
* and objects created by constructors other than `Object` are cloned to plain
* `Object` objects.
*
* Note: Lo-Dash's deep clone functionality is loosely based on the structured clone algorithm.
* See http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm.
* *
* @static * @static
* @memberOf _ * @memberOf _
@@ -995,9 +989,6 @@
* { 'name': 'curly', 'age': 60 } * { 'name': 'curly', 'age': 60 }
* ]; * ];
* *
* _.clone({ 'name': 'moe' });
* // => { 'name': 'moe' }
*
* var shallow = _.clone(stooges); * var shallow = _.clone(stooges);
* shallow[0] === stooges[0]; * shallow[0] === stooges[0];
* // => true * // => true
@@ -1076,6 +1067,35 @@
return result; return result;
} }
/**
* Creates a deep clone of `value`. Functions and DOM nodes are **not** cloned.
* The enumerable properties of `arguments` objects and objects created by
* constructors other than `Object` are cloned to plain `Object` objects.
*
* Note: Lo-Dash's deep clone functionality is loosely based on the structured clone algorithm.
* See http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to deep clone.
* @returns {Mixed} Returns the deep cloned `value`.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 },
* { 'name': 'curly', 'age': 60 }
* ];
*
* var deep = _.cloneDeep(stooges);
* deep[0] === stooges[0];
* // => false
*/
function cloneDeep(value) {
return clone(value, true);
}
/** /**
* Assigns own enumerable properties of source object(s) to the `destination` * Assigns own enumerable properties of source object(s) to the `destination`
* object for all `destination` properties that resolve to `null`/`undefined`. * object for all `destination` properties that resolve to `null`/`undefined`.
@@ -3730,8 +3750,6 @@
/** /**
* This function returns the first argument passed to it. * This function returns the first argument passed to it.
* *
* Note: This function is used throughout Lo-Dash as a default callback.
*
* @static * @static
* @memberOf _ * @memberOf _
* @category Utilities * @category Utilities
@@ -4257,6 +4275,7 @@
// add functions that return unwrapped values when chaining // add functions that return unwrapped values when chaining
lodash.clone = clone; lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.contains = contains; lodash.contains = contains;
lodash.escape = escape; lodash.escape = escape;
lodash.every = every; lodash.every = every;

View File

@@ -147,6 +147,7 @@
var objectsMethods = [ var objectsMethods = [
'assign', 'assign',
'clone', 'clone',
'cloneDeep',
'defaults', 'defaults',
'extend', 'extend',
'forIn', 'forIn',
@@ -248,6 +249,7 @@
/** List of methods used by Underscore */ /** List of methods used by Underscore */
var underscoreMethods = _.without.apply(_, [allMethods].concat([ var underscoreMethods = _.without.apply(_, [allMethods].concat([
'bindKey', 'bindKey',
'cloneDeep',
'forIn', 'forIn',
'forOwn', 'forOwn',
'isPlainObject', 'isPlainObject',

View File

@@ -243,7 +243,7 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
QUnit.module('lodash.clone'); QUnit.module('cloning');
(function() { (function() {
function Klass() { this.a = 1; } function Klass() { this.a = 1; }
@@ -277,7 +277,7 @@
_.forOwn(objects, function(object, key) { _.forOwn(objects, function(object, key) {
test('should deep clone ' + key, function() { test('should deep clone ' + key, function() {
var clone = _.clone(object, true); var clone = _.cloneDeep(object);
ok(_.isEqual(object, clone)); ok(_.isEqual(object, clone));
if (_.isObject(object)) { if (_.isObject(object)) {
@@ -291,7 +291,7 @@
_.forOwn(nonCloneable, function(object, key) { _.forOwn(nonCloneable, function(object, key) {
test('should not clone ' + key, function() { test('should not clone ' + key, function() {
strictEqual(_.clone(object), object); strictEqual(_.clone(object), object);
strictEqual(_.clone(object, true), object); strictEqual(_.cloneDeep(object), object);
}); });
}); });
@@ -304,7 +304,7 @@
test('should deep clone `index` and `input` array properties', function() { test('should deep clone `index` and `input` array properties', function() {
var array = /x/.exec('x'), var array = /x/.exec('x'),
actual = _.clone(array, true); actual = _.cloneDeep(array);
equal(actual.index, 0); equal(actual.index, 0);
equal(actual.input, 'x'); equal(actual.input, 'x');
@@ -319,15 +319,15 @@
object.foo.b.foo.c = object; object.foo.b.foo.c = object;
object.bar.b = object.foo.b; object.bar.b = object.foo.b;
var clone = _.clone(object, true); var clone = _.cloneDeep(object);
ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object); ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object);
}); });
test('should clone problem JScript properties (test in IE < 9)', function() { test('should clone problem JScript properties (test in IE < 9)', function() {
deepEqual(_.clone(shadowed), shadowed); deepEqual(_.clone(shadowed), shadowed);
notEqual(_.clone(shadowed), shadowed); notEqual(_.clone(shadowed), shadowed);
deepEqual(_.clone(shadowed, true), shadowed); deepEqual(_.cloneDeep(shadowed), shadowed);
notEqual(_.clone(shadowed, true), shadowed); notEqual(_.cloneDeep(shadowed), shadowed);
}); });
}(1, 2, 3)); }(1, 2, 3));