From 9836b274b9abf4818890cbf6543261876a968fe9 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 18 Jul 2012 03:55:16 -0400 Subject: [PATCH] Add `_.drop`, unit tests, and cleanup documentation for `_.extend`, `_.defaults`, and `_.pick`. Former-commit-id: a45b0c45d52fdbe5f71984412d631f3dfe87965b --- build.js | 1 + build/pre-compile.js | 4 +++ lodash.js | 64 +++++++++++++++++++++++++++++++------------- test/test.js | 41 ++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/build.js b/build.js index 0f56e4081..a2d1c93cb 100755 --- a/build.js +++ b/build.js @@ -155,6 +155,7 @@ 'defer': [], 'delay': [], 'difference': ['indexOf'], + 'drop': ['indexOf'], 'escape': [], 'every': ['identity'], 'extend': [], diff --git a/build/pre-compile.js b/build/pre-compile.js index 7e0c04944..7da3dab10 100644 --- a/build/pre-compile.js +++ b/build/pre-compile.js @@ -10,17 +10,20 @@ 'accumulator', 'args', 'arrayClass', + 'ArrayProto', 'bind', 'callback', 'className', 'collection', 'compareAscending', + 'concat', 'ctor', 'funcClass', 'funcs', 'hasOwnProperty', 'identity', 'index', + 'indexOf', 'isFunc', 'iteratee', 'iterateeIndex', @@ -97,6 +100,7 @@ 'delay', 'detect', 'difference', + 'drop', 'each', 'environment', 'escape', diff --git a/lodash.js b/lodash.js index b388c0a02..8422da923 100644 --- a/lodash.js +++ b/lodash.js @@ -575,16 +575,16 @@ } // create the function factory var factory = Function( - 'arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity, ' + - 'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice, ' + - 'stringClass, toString', + 'arrayClass, ArrayProto, bind, compareAscending, concat, funcClass, ' + + 'hasOwnProperty, identity, indexOf, iteratorBind, objectTypes, nativeKeys, ' + + 'propertyIsEnumerable, slice, stringClass, toString', 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' ); // return the compiled function return factory( - arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity, - iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice, - stringClass, toString + arrayClass, ArrayProto, bind, compareAscending, concat, funcClass, + hasOwnProperty, identity, indexOf, iteratorBind, objectTypes, nativeKeys, + propertyIsEnumerable, slice, stringClass, toString ); } @@ -2449,16 +2449,17 @@ } /** - * Assigns missing properties on `object` with default values from the defaults - * objects. Once a property is set, additional defaults of the same property - * will be ignored. + * Assigns enumerable properties of the default object(s) to the `destination` + * object for all `destination` properties that resolve to `null`/`undefined`. + * Once a property is set, additional defaults of the same property will be + * ignored. * * @static * @memberOf _ * @category Objects - * @param {Object} object The object to populate. - * @param {Object} [defaults1, defaults2, ...] The defaults objects to apply to `object`. - * @returns {Object} Returns `object`. + * @param {Object} object The destination object. + * @param {Object} [default1, default2, ...] The default objects. + * @returns {Object} Returns the `object`. * @example * * var iceCream = { 'flavor': 'chocolate' }; @@ -2470,15 +2471,40 @@ }); /** - * Copies enumerable properties from the source objects to the `destination` object. - * Subsequent sources will overwrite propery assignments of previous sources. + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Object} [prop1, prop2, ...] The properties to drop. + * @returns {Object} Returns an object without the dropped properties. + * @example + * + * _.drop({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid'); + * // => { 'name': 'moe', 'age': 40 } + */ + var drop = createIterator({ + 'useHas': false, + 'args': 'object', + 'init': '{}', + 'top': 'var props = concat.apply(ArrayProto, arguments)', + 'inLoop': 'if (indexOf(props, index) < 0) result[index] = iteratee[index]' + }); + + /** + * Assigns enumerable properties of the source object(s) to the `destination` + * object. Subsequent sources will overwrite propery assignments of previous + * sources. * * @static * @memberOf _ * @category Objects * @param {Object} object The destination object. * @param {Object} [source1, source2, ...] The source objects. - * @returns {Object} Returns the destination object. + * @returns {Object} Returns the `object`. * @example * * _.extend({ 'name': 'moe' }, { 'age': 40 }); @@ -3080,13 +3106,14 @@ }; /** - * Creates an object composed of the specified properties. Property names may - * be specified as individual arguments or as arrays of property names. + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. * * @static * @memberOf _ * @category Objects - * @param {Object} object The object to pluck. + * @param {Object} object The source object. * @param {Object} [prop1, prop2, ...] The properties to pick. * @returns {Object} Returns an object composed of the picked properties. * @example @@ -3632,6 +3659,7 @@ lodash.defer = defer; lodash.delay = delay; lodash.difference = difference; + lodash.drop = drop; lodash.escape = escape; lodash.every = every; lodash.extend = extend; diff --git a/test/test.js b/test/test.js index 9f8c71789..08662de9c 100644 --- a/test/test.js +++ b/test/test.js @@ -201,6 +201,34 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.drop'); + + (function() { + var object = { 'a': 1, 'b': 2, 'c': 3 }, + actual = { 'b': 2 }; + + test('should accept individual property names', function() { + deepEqual(_.drop(object, 'a', 'c'), actual); + }); + + test('should accept an array of property names', function() { + deepEqual(_.drop(object, ['a', 'c']), actual); + }); + + test('should accept mixes of individual and arrays of property names', function() { + deepEqual(_.drop(object, ['a'], 'c'), actual); + }); + + test('should iterate over inherited properties', function() { + function Foo() {} + Foo.prototype = object; + + deepEqual(_.drop(new Foo, 'a', 'c'), actual); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.escape'); (function() { @@ -642,6 +670,19 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.pick'); + + (function() { + test('should iterate over inherited properties', function() { + function Foo() {} + Foo.prototype = { 'a': 1, 'b': 2, 'c': 3 }; + + deepEqual(_.pick(new Foo, 'b'), { 'b': 2 }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.pluck'); (function() {