From b57fe466cef58b62eef5abb3b14d5bce11655e3a Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 20 Nov 2012 07:32:51 -0800 Subject: [PATCH] =?UTF-8?q?Make=20`=5F(=E2=80=A6)`=20wrapper=20versions=20?= =?UTF-8?q?of=20`=5F.first`=20and=20`=5F.last`=20capable=20of=20returning?= =?UTF-8?q?=20wrapped=20and=20unwrapped=20values.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Former-commit-id: b30704c1ce359213aa09069b290ee55edfb3e33e --- build.js | 8 +++++--- lodash.js | 22 +++++++++++++++++----- test/test-build.js | 12 ++++++------ test/test.js | 38 ++++++++++++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/build.js b/build.js index b3a70f6bc..70dc46ed5 100755 --- a/build.js +++ b/build.js @@ -1397,9 +1397,6 @@ }); }); - // remove Lo-Dash specific `lodash.prototype` extensions - source = source.replace(/(?:\s*\/\/.*)*\n( *)forEach\(filter[\s\S]+?lodash\.[\s\S]+?\n\1}.+/, ''); - // remove unneeded template related variables source = removeVar(source, 'reComplexDelimiter'); source = removeVar(source, 'reEmptyStringLeading'); @@ -1419,6 +1416,11 @@ // remove `lodash.prototype.toString` and `lodash.prototype.valueOf` assignments source = source.replace(/ *lodash\.prototype\.(?:toString|valueOf) *=.+\n/g, ''); + // remove `lodash.prototype` batch method assignments + source = source + .replace(/(?:\s*\/\/.*)*\n( *)forEach\(\['first'[\s\S]+?\n\1}.+/, '') + .replace(/(?:\s*\/\/.*)*\n( *)forEach\(filter[\s\S]+?lodash\.[\s\S]+?\n\1}.+/, ''); + // remove unused features from `createBound` if (buildMethods.indexOf('partial') == -1) { source = source.replace(matchFunction(source, 'createBound'), function(match) { diff --git a/lodash.js b/lodash.js index 645f26cbd..cff22dfc4 100644 --- a/lodash.js +++ b/lodash.js @@ -4225,11 +4225,23 @@ lodash.prototype.value = wrapperValue; lodash.prototype.valueOf = wrapperValue; - // add all methods that return non-wrapped values + // add methods that are capable of returning wrapped and unwrapped values + forEach(['first', 'last'], function(methodName) { + var func = lodash[methodName]; + if (func) { + lodash.prototype[methodName] = function(n, guard) { + var result = func(this.__wrapped__, n, guard); + return (n == null || guard) + ? result + : new lodash(result); + }; + } + }); + + // add all methods that return unwrapped values forEach(filter(functions(lodash), function(methodName) { - return /^(?:contains|every|find|first|has|is[A-Z].+|last|reduce.*|some)$/.test(methodName); - }), - function(methodName) { + return /^(?:contains|every|find|has|is[A-Z].+|reduce.*|some)$/.test(methodName); + }), function(methodName) { var func = lodash[methodName]; lodash.prototype[methodName] = function() { @@ -4252,7 +4264,7 @@ if (hasObjectSpliceBug && value.length === 0) { delete value[0]; } - return new lodash(value); + return this; }; }); diff --git a/test/test-build.js b/test/test-build.js index fcc807f50..35cc45ec7 100644 --- a/test/test-build.js +++ b/test/test-build.js @@ -695,13 +695,13 @@ equal(lodash.some([false, true, false]), true, '_.some: ' + basename); equal(lodash.template('${a}', object), '${a}', '_.template should ignore ES6 delimiters: ' + basename); - object = lodash(1); - equal(object.clone() instanceof lodash, false, '_(...) wrapped values are not chainable by default: ' + basename); - equal(String(object) === '1', false, '_#toString should not be implemented: ' + basename); - equal(Number(object) === 1 , false, '_#valueOf should not be implemented: ' + basename); + var wrapped = lodash(1); + equal(wrapped.clone() instanceof lodash, false, '_(...) wrapped values are not chainable by default: ' + basename); + equal(String(wrapped) === '1', false, '_#toString should not be implemented: ' + basename); + equal(Number(wrapped) === 1 , false, '_#valueOf should not be implemented: ' + basename); - object.chain(); - equal(typeof object.has('x') == 'object', true, '_#has returns wrapped values when chaining: ' + basename); + wrapped.chain(); + equal(wrapped.has('x') instanceof lodash, true, '_#has returns wrapped values when chaining: ' + basename); start(); }); diff --git a/test/test.js b/test/test.js index b0d4f4655..4f617e30e 100644 --- a/test/test.js +++ b/test/test.js @@ -1957,10 +1957,35 @@ /*--------------------------------------------------------------------------*/ - QUnit.module('lodash(...) methods returning non-wrapped values'); + QUnit.module('lodash(...) methods capable of returning wrapped and unwrapped values'); (function() { - var array = [1, 2, 3]; + var array = [1, 2, 3], + wrapped = _(array); + + var funcs = [ + 'first', + 'last' + ]; + + _.each(funcs, function(methodName) { + test('_.' + methodName + ' should return an unwrapped value', function() { + equal(typeof wrapped[methodName](), 'number'); + }); + + test('_.' + methodName + ' should return a wrapped value', function() { + ok(wrapped[methodName](1) instanceof _); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash(...) methods that return unwrapped values'); + + (function() { + var array = [1, 2, 3], + wrapped = _(array); var funcs = [ 'contains', @@ -1992,11 +2017,12 @@ ]; _.each(funcs, function(methodName) { - test('_.' + methodName + ' should return non-wrapped values', function() { - var func = _[methodName], - result = methodName == 'reduceRight' ? func(array, _.identity) : func; + test('_.' + methodName + ' should return unwrapped values', function() { + var result = methodName == 'reduceRight' + ? wrapped[methodName](_.identity) + : wrapped[methodName]; - notEqual(typeof result, 'object', '_.' + methodName + ' returns non-wrapped values'); + notEqual(typeof result, 'object', '_.' + methodName + ' returns unwrapped values'); }); }); }());