191

Is it possible to pass a javascript function with arguments as an argument?

Example:

$(edit_link).click( changeViewMode( myvar ) );
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Lucia
  • 4,657
  • 6
  • 43
  • 57
  • 5
    It looks like JQuery, and most likely is, but that is irrelevant. The use or parameters and functions is the same regardless of what Javascript libraries you use. – Guffa Aug 19 '09 at 14:18
  • 1
    If you are working with React, consider https://stackoverflow.com/questions/41369497/passing-a-function-with-parameters-through-props-on-reactjs – Michael Freidgeim Feb 03 '20 at 01:22

7 Answers7

301

Use a "closure":

$(edit_link).click(function(){ return changeViewMode(myvar); });

This creates an anonymous temporary function wrapper that knows about the parameter and passes it to the actual callback implementation.

Ferdinand Beyer
  • 64,979
  • 15
  • 154
  • 145
  • 3
    If you're wanting to call a function on an object, you need to call bind(). myObj.click( function() { this.doSomething(); }.bind( myObj ) ); That will make "this" be myObj. – Eli Oct 03 '13 at 22:19
  • 1
    Isn't this a performance issue when dealing with a lot of these? E.g. You're rendering a onPress in a Row and you have 10,000 rows. This creates a new anonymous temporary function wrapper for each Row. Is there any other way to do it? – Joshua Pinter Nov 26 '17 at 18:23
  • 3
    @JoshuaPinter The technique itself is not an issue. If you need the same function call 10,000 times, you can simply save the wrapper in a variable, so you create it only once. If you need to pass 10,000 different contexts, there is little you can do. Beware of premature optimization: As always with performance, you need to *measure* to see if there is a problem or not. Today's JavaScript engines are very powerful and might optimize code in surprising ways. – Ferdinand Beyer Nov 27 '17 at 09:49
  • @FerdinandBeyer Awesome, thanks for the tip. A friend told me it was bad practice and that you should instead use `this.myFunction = this.myFunction.bind(this)` in your `constructor` method. But, like you said, when you have to pass different contexts to it for each one, like all different rows that you click on to open that row's detail page, it's not avoidable. – Joshua Pinter Nov 27 '17 at 23:41
  • @FerdinandBeyer , lets say myvar is a string and its changed between two consecutive invocations of passing changeViewMode as a closure, but changeViewMode always receives the first value of myvar , I want to call closure function with different argument value assigned to same myvar variable, – nmxprime Jul 18 '19 at 07:00
  • 1
    In ES6 you can simplify it by using arrow functions. $(edit_link).click(() => changeViewMode(myvar)); – rodrigombs Nov 22 '20 at 02:10
52

Use Function.prototype.bind(). Quoting MDN:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

It is supported by all major browsers, including IE9+.

Your code should look like this:

$(edit_link).click(changeViewMode.bind(null, myvar));

Side note: I assume you are in global context, i.e. this variable is window; otherwise use this instead of null.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • Thanks, this helped me. Used it like this: `$.ajax(url).done(handler.bind(this, var1, var2));` – Thomas Jun 16 '16 at 10:13
  • 2
    Which option is best ? Using closure or using the bind function ? Please let me know if there is any performance impact – Varun Sep 07 '16 at 08:50
  • 5
    @Varun See [Why is bind slower than a closure?](http://stackoverflow.com/questions/17638305/why-is-bind-slower-than-a-closure) – Michał Perłakowski Sep 07 '16 at 13:48
  • I've been using `fn.bind(this)` to resolve the dreaded `this` confusion in callback functions without understanding the broader purpose of `bind` – but now I get it! Thanks – flatpickles Jun 07 '22 at 05:58
19

No, but you can pass one without parameters, and do this:

$(edit_link).click(
  function() { changeViewMode(myvar); }
);

So you're passing an anonymous function with no parameters, that function then calls your parameterized function with the variable in the closure

Clyde
  • 8,017
  • 11
  • 56
  • 87
15

Or if you are using es6 you should be able to use an arrow function

$(edit_link).click(() => changeViewMode(myvar));
8

Yes, like this:

$(edit_link).click(function() { changeViewMode(myvar) });
Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
3

You can do this

var message  = 'Hello World';

var callback = function(){
alert(this)
}.bind(message);

and then

function activate(callback){
  callback && callback();
}

activate(callback);

Or if your callback contains more flexible logic you can pass object.

Demo

Alexandr Sargsyan
  • 656
  • 1
  • 6
  • 21
2

This is an example following Ferdinand Beyer's approach:

function function1()
{
    function2(function () { function3("parameter value"); });
}
function function2(functionToBindOnClick)
{
    $(".myButton").click(functionToBindOnClick);
}
function function3(message) { alert(message); }

In this example the "parameter value" is passed from function1 to function3 through function2 using a function wrap.

erionpc
  • 368
  • 3
  • 15