diff --git a/lodash.js b/lodash.js index 4f508fffc..8e45fd2e7 100644 --- a/lodash.js +++ b/lodash.js @@ -1809,21 +1809,21 @@ * @returns {Array} Returns a new array of composed arguments. */ function composeArgs(partialArgs, partialHolders, args) { - var index = -1, - length = partialHolders.length, + var holdersLength = partialHolders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partialArgs.length, - argsLength = nativeMax(args.length - length, 0), result = Array(argsLength + leftLength); while (++leftIndex < leftLength) { result[leftIndex] = partialArgs[leftIndex]; } - while (++index < length) { - result[partialHolders[index]] = args[index]; + while (++argsIndex < holdersLength) { + result[partialHolders[argsIndex]] = args[argsIndex]; } - while (length < argsLength) { - result[leftIndex++] = args[length++]; + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; } return result; } @@ -1839,10 +1839,10 @@ * @returns {Array} Returns a new array of composed arguments. */ function composeArgsRight(partialRightArgs, partialRightHolders, args) { - var index = -1, - length = partialRightHolders.length, + var holdersIndex = -1, + holdersLength = partialRightHolders.length, argsIndex = -1, - argsLength = nativeMax(args.length - length, 0), + argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partialRightArgs.length, result = Array(argsLength + rightLength); @@ -1854,8 +1854,8 @@ while (++rightIndex < rightLength) { result[pad + rightIndex] = partialRightArgs[rightIndex]; } - while (++index < length) { - result[pad + partialHolders[index]] = args[argsIndex++]; + while (++holdersIndex < holdersLength) { + result[pad + partialRightHolders[holdersIndex]] = args[argsIndex++]; } return result; } diff --git a/test/test.js b/test/test.js index 1f03e02d5..24ec3c722 100644 --- a/test/test.js +++ b/test/test.js @@ -5950,57 +5950,91 @@ isPartial = methodName == 'partial'; test('`_.' + methodName + '` partially applies arguments', 1, function() { - var fn = function(a) { return a; }; - equal(func(fn, 'a')(), 'a'); + var fn = function(a) { return a; }, + par = func(fn, 'a'); + + equal(par(), 'a'); }); test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() { var fn = function(a, b) { return [a, b]; }, - expected = ['a', 'b']; + expected = ['a', 'b'], + par = func(fn, 'a'); - if (!isPartial) { - expected.reverse(); - } - deepEqual(func(fn, 'a')('b'), expected); + deepEqual(par('b'), isPartial ? expected : expected.reverse()); }); test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked without additional arguments', 1, function() { - var fn = function() { return arguments.length; }; - strictEqual(func(fn)(), 0); + var fn = function() { return arguments.length; }, + par = func(fn); + + strictEqual(par(), 0); }); test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() { - var fn = function(a) { return a; }; - equal(func(fn)('a'), 'a'); + var fn = function(a) { return a; }, + par = func(fn); + + equal(par('a'), 'a'); }); test('`_.' + methodName + '` should not alter the `this` binding', 3, function() { var fn = function() { return this.a; }, object = { 'a': 1 }; - strictEqual(func(_.bind(fn, object))(), object.a); - strictEqual(_.bind(func(fn), object)(), object.a); + var par = func(_.bind(fn, object)); + strictEqual(par(), object.a); - object.partialed = func(fn); - strictEqual(object.partialed(), object.a); + par = _.bind(func(fn), object); + strictEqual(par(), object.a); + + object.par = func(fn); + strictEqual(object.par(), object.a); }); test('`_.' + methodName + '` creates a function with a `length` of `0`', 1, function() { var fn = function(a, b, c) {}, - actual = func(fn, 'a'); + par = func(fn, 'a'); - strictEqual(actual.length, 0); + strictEqual(par.length, 0); }); test('`_.' + methodName + '` ensure `new partialed` is an instance of `func`', 2, function() { function Foo(value) { return value && object; } - var partialed = func(Foo), + var par = func(Foo), object = {}; - ok(new partialed instanceof Foo); - strictEqual(new partialed(true), object); + ok(new par instanceof Foo); + strictEqual(new par(true), object); + }); + + test('`_.' + methodName + '` should support placeholders', 4, function() { + if (_._iteratorTemplate) { + var fn = function() { + return _.reduce(arguments, function(string, chr) { + return string + (chr || ''); + }, ''); + }; + + var par = func(fn, _, 'b', _); + equal(par('a', 'c'), 'abc'); + equal(par('a'), 'ab'); + + if (isPartial) { + equal(par('a', 'c', 'd'), 'abcd'); + } else { + par = func(fn, _, 'c', _); + equal(par('a', 'b', 'd'), 'abcd'); + } + fn = function() { return slice.call(arguments); }; + par = func(fn, _, 'b', _); + deepEqual(par(), [undefined, 'b', undefined]); + } + else { + skipTest(4); + } }); test('`_.' + methodName + '` should clone metadata for created functions', 3, function() {