How can I pass a reference to a function, with parameters?

JavascriptPass by-ReferenceAnonymous Function

Javascript Problem Overview


> 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);
  };
}

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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
*/

Solution 3 - Javascript

The following is equivalent to your second code block:

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

var fr = f;

fr(pars);

If you want to actually pass a reference to a function to some other function, you can do something like this:

function fiz(x, y, z) {
    return x + y + z;
}

// elsewhere...

function foo(fn, p, q, r) {
    return function () {
        return fn(p, q, r);
    }
}

// finally...

f = foo(fiz, 1, 2, 3);
f(); // returns 6

You're almost certainly better off using a framework for this sort of thing, though.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndreas GrechView Question on Stackoverflow
Solution 1 - JavascriptJason BuntingView Answer on Stackoverflow
Solution 2 - JavascriptSZ__View Answer on Stackoverflow
Solution 3 - JavascriptlawnseaView Answer on Stackoverflow