755
votes

How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)

I have this:

addContact(entityId, refreshContactList());

It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.

I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?

14

14 Answers

1046
votes

You just need to remove the parenthesis:

addContact(entityId, refreshContactList);

This then passes the function without executing it first.

Here is an example:

function addContact(id, refreshCallback) {
    refreshCallback();
    // You can also pass arguments if you need to
    // refreshCallback(id);
}

function refreshContactList() {
    alert('Hello World');
}

addContact(1, refreshContactList);
419
votes

If you want to pass a function, just reference it by name without the parentheses:

function foo(x) {
    alert(x);
}
function bar(func) {
    func("Hello World!");
}

//alerts "Hello World!"
bar(foo);

But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:

function foo(x) {
   alert(x);
}
function bar(func) {
   func();
}

//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });

If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:

function eat(food1, food2)
{
    alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args)
{
    //do stuff
    //...
    //execute callback when finished
    callback.apply(this, args);
}

//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]); 
57
votes

Example 1:

funct("z", function (x) { return x; });

function funct(a, foo){
    foo(a) // this will return a
}

Example 2:

function foodemo(value){
    return 'hello '+value;
}

function funct(a, foo){
    alert(foo(a));
}

//call funct    
funct('world!',foodemo); //=> 'hello world!'

look at this

38
votes

To pass the function as parameter, simply remove the brackets!

function ToBeCalled(){
  alert("I was called");
}

function iNeedParameter( paramFunc) {
   //it is a good idea to check if the parameter is actually not null
   //and that it is a function
   if (paramFunc && (typeof paramFunc == "function")) {
      paramFunc();   
   }
}

//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled); 

The idea behind this is that a function is quite similar to a variable. Instead of writing

function ToBeCalled() { /* something */ }

you might as well write

var ToBeCalledVariable = function () { /* something */ }

There are minor differences between the two, but anyway - both of them are valid ways to define a function. Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:

anotherFunction(ToBeCalledVariable);
18
votes

There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!

In addition to Steve Fenton's answer, you can also pass functions directly.

function addContact(entity, refreshFn) {
    refreshFn();
}

function callAddContact() {
    addContact("entity", function() { DoThis(); });
}
10
votes

I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :

function foo(blabla){
    var func = new Function(blabla);
    func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");

And that's working like a charm ... for what I needed at least. Hope it might help some.

8
votes

I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.

function addContact(parameters, refreshCallback) {
    refreshCallback.apply(this, parameters);
}

function refreshContactList(int, int, string) {
    alert(int + int);
    console.log(string);
}

addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
6
votes

You can also use eval() to do the same thing.

//A function to call
function needToBeCalled(p1, p2)
{
    alert(p1+"="+p2);
}

//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
    eval(aFunction + "("+params+")");
}

//A function Call
callAnotherFunction("needToBeCalled", "10,20");

That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.

3
votes

Here it's another approach :

function a(first,second)    
{        
return (second)(first);           
}     

a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world     
3
votes

In fact, seems like a bit complicated, is not.

get method as a parameter:

 function JS_method(_callBack) { 

           _callBack("called");  

        }

You can give as a parameter method:

    JS_method(function (d) {
           //Finally this will work.
           alert(d)
    });
3
votes

The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.

For instance, if you pass through a string instead of a function you'll get an error:

function function1(my_function_parameter){
    my_function_parameter();   
}

function function2(){
 alert('Hello world');   
}

function1(function2); //This will work

function1("function2"); //This breaks!

See JsFiddle

1
votes

Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.

I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below

ORIGINALLY

    <button className="img-submit" type="button"  onClick=
 {onSubmit}>Upload Image</button>

MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments

<button className="img-submit" type="button"  onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>

upload(event,fn){
  //custom codes are done here
  fn(event);
}
0
votes

By using ES6:


const invoke = (callback) => {
  callback()
}


invoke(()=>{
  console.log("Hello World");
})
-2
votes

You can use a JSON as well to store and send JS functions.

Check the following:

var myJSON = 
{
    "myFunc1" : function (){
        alert("a");
    }, 
    "myFunc2" : function (functionParameter){
        functionParameter();
    }
}



function main(){
    myJSON.myFunc2(myJSON.myFunc1);
}

This will print 'a'.

The following has the same effect with the above:

var myFunc1 = function (){
    alert('a');
}

var myFunc2 = function (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Which is also has the same effect with the following:

function myFunc1(){
    alert('a');
}


function myFunc2 (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

And a object paradigm using Class as object prototype:

function Class(){
    this.myFunc1 =  function(msg){
        alert(msg);
    }

    this.myFunc2 = function(callBackParameter){
        callBackParameter('message');
    }
}


function main(){    
    var myClass = new Class();  
    myClass.myFunc2(myClass.myFunc1);
}