From 789da94fb288f643f189b8dfa056b956843bbcea Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Wed, 30 Jan 2013 12:35:56 +1100 Subject: [PATCH] Fixes #474 -- add _.partial --- test/functions.js | 12 ++++++++++-- underscore.js | 14 +++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/test/functions.js b/test/functions.js index 44cf39dda..efa9934d3 100644 --- a/test/functions.js +++ b/test/functions.js @@ -18,10 +18,10 @@ $(document).ready(function() { func = _.bind(func, this, 'hello'); equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); - var func = _.bind(func, this, 'curly'); + func = _.bind(func, this, 'curly'); equal(func(), 'hello: curly', 'the function was completely applied in advance'); - var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; + func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; func = _.bind(func, this, 'hello', 'moe', 'curly'); equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); @@ -37,6 +37,14 @@ $(document).ready(function() { equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); }); + test("partial", function() { + var obj = {name: 'moe'}; + var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); }; + + obj.func = _.partial(func, 'a', 'b'); + equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); + }); + test("bindAll", function() { var curly = {name : 'curly'}, moe = { name : 'moe', diff --git a/underscore.js b/underscore.js index ee8660d07..9ffdf15bb 100644 --- a/underscore.js +++ b/underscore.js @@ -578,9 +578,8 @@ var ctor = function(){}; // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Binding with arguments is also known as `curry`. - // Delegates to **ECMAScript 5**'s native `Function.bind` if available. - // We check for `func.bind` first, to fail fast when `func` is undefined. + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. _.bind = function(func, context) { if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); var args = slice.call(arguments, 2); @@ -589,6 +588,15 @@ }; }; + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + // Bind all of an object's methods to that object. Useful for ensuring that // all callbacks defined on an object belong to it. _.bindAll = function(obj) {