diff --git a/test/functions.js b/test/functions.js index 045b4dcb2..de2be68e7 100644 --- a/test/functions.js +++ b/test/functions.js @@ -478,6 +478,22 @@ composed = _.compose(greet, exclaim); equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); + + // f(g(h(x, y, z))) + function h(x, y, z) { + equal(arguments.length, 3, 'First function called with multiple args'); + return z * y; + }; + function g(x) { + equal(arguments.length, 1, 'Composed function is called with 1 argument'); + return x; + }; + function f(x) { + equal(arguments.length, 1, 'Composed function is called with 1 argument'); + return x * 2; + }; + composed = _.compose(f, g, h); + equal(composed(1, 2, 3), 12); }); test('after', function() { diff --git a/underscore.js b/underscore.js index 708ebe066..5204e0e03 100644 --- a/underscore.js +++ b/underscore.js @@ -804,13 +804,14 @@ // Returns a function that is the composition of a list of functions, each // consuming the return value of the function that follows. _.compose = function() { - var funcs = arguments; + var funcs = arguments, length = funcs.length; return function() { - var args = arguments; - for (var i = funcs.length - 1; i >= 0; i--) { - args = [funcs[i].apply(this, args)]; + var idx = length - 1, + result = funcs[idx].apply(this, arguments); + while (idx--) { + result = funcs[idx].call(this, result); } - return args[0]; + return result; }; };