95

Possible Duplicate:
How can I pre-set arguments in JavaScript function call? (Partial Function Application)

I need to able to pass a reference to a function with a given set of parameters.

Here is an example of passing a reference without parameters:

var f = function () {
    //Some logic here...
};

var fr = f; //Here I am passing a reference to function 'f', without parameters
fr(); //the 'f' function is invoked, without parameters

Now what I need to do is pass the same f function, but this time I would need to pass parameters to the reference. Now, I can do it with an anonymous function and invoke the f function with parameters inside the newly created function, like such:

var f = function () {
        //Some logic here...
    };

var fr = function (pars) {
    f(pars);
}; //Here I am creating an anonymous function, and invoking f inside it

fr({p : 'a parameter'}); //Invoking the fr function, that will later invoke the f function with parameters

But my question is, Is there a way to pass a direct reference to the f function With parameters to fr, but without enclosing it in an anonymous function?

What do I need to assign to fr to make it invokable without parameters (fr()), so that f(1,2,3) is executed when fr is invoked?

[UPDATE] I followed Jason Bunting's answer to here about the Partial Function and the JavaScript function he posts there is exactly what I was looking for. Here is the solution:

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments).splice(1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}
2
  • For some reason, I had trouble with the first statement (var args = Array.prototype.slice.call(arguments).splice(1);) and had to use this instead: var args = new Array(); for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); } Commented Jan 22, 2009 at 21:28
  • just in case anyone needs this: Function.prototype.pass = function(){ var args=arguments, func = this; return function(){ func.apply(this,args);} }; Commented Apr 15, 2014 at 2:20

2 Answers 2

81

What you are after is called partial function application.

Don't be fooled by those that don't understand the subtle difference between that and currying, they are different.

Partial function application can be used to implement, but is not currying. Here is a quote from a blog post on the difference:

Where partial application takes a function and from it builds a function which takes fewer arguments, currying builds functions which take multiple arguments by composition of functions which each take a single argument.

This has already been answered, see this question for your answer: How can I pre-set arguments in JavaScript function call?

Example:

var fr = partial(f, 1, 2, 3);

// now, when you invoke fr() it will invoke f(1,2,3)
fr();

Again, see that question for the details.

Sign up to request clarification or add additional context in comments.

3 Comments

What do I need to assign to fr to make it invokable without parameters (fr()), so that f(1,2,3) is executed when fr is invoked
Note for future readers, make sure you include the partial function provided by Jason in his other answer
As an alternative to Jason's partial function, the UnderscoreJS library offers a _.partial function as well.
2

You can also overload the Function prototype:

// partially applies the specified arguments to a function, returning a new function
Function.prototype.curry = function( ) {
    var func = this;
    var slice = Array.prototype.slice;
    var appliedArgs = slice.call( arguments, 0 );

    return function( ) {
        var leftoverArgs = slice.call( arguments, 0 );
        return func.apply( this, appliedArgs.concat( leftoverArgs ) );
    };
};

// can do other fancy things:

// flips the first two arguments of a function
Function.prototype.flip = function( ) {
    var func = this;
    return function( ) {
        var first = arguments[0];
        var second = arguments[1];
        var rest = Array.prototype.slice.call( arguments, 2 );
        var newArgs = [second, first].concat( rest );

        return func.apply( this, newArgs );
    };
};

/*
e.g.

var foo = function( a, b, c, d ) { console.log( a, b, c, d ); }
var iAmA = foo.curry( "I", "am", "a" );
iAmA( "Donkey" );
-> I am a Donkey

var bah = foo.flip( );
bah( 1, 2, 3, 4 );
-> 2 1 3 4
*/

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.