854

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?

Nic
  • 6,211
  • 10
  • 46
  • 69
imperium2335
  • 23,402
  • 38
  • 111
  • 190

16 Answers16

1175

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);
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • 7
    Based on the question, the callback doesn't accept parameters, which is why I have left them out of the example. I'll add a comment about it. – Fenton Nov 08 '12 at 09:42
  • 1
    How would it look like to pass an anonymous function instead of a pre-defined one ? – Veverke Oct 21 '14 at 13:49
  • 6
    @Veverke It would look like this... `addContact(1, function(id) { console.log(id); });` – Fenton Nov 24 '14 at 10:46
  • @user6031759 you'd need to share your code so we can help you. – Fenton Jun 20 '16 at 16:07
  • class myFuncs = { changeColor: function(targetClass = null, targetId = null, targetTagName = null, animated, myFunc) { /*Error here*/ myFunc(); } }; – user6031759 Jun 20 '16 at 22:12
  • 1
    The class syntax in ECMAScript wouldn't have an `=` sign... `class myFuncs {` rather than `class myFuncs = {`. You'd also need to be running in an environment that supported the class syntax (not all browsers support it yet). If you are still struggling, it might be better suited to a whole new question as your problem isn't about passing functions - it is general ES syntax. – Fenton Jun 21 '16 at 21:08
  • 1
    How calling this `App.ThisFunction("show")` function on another? for example: `myotherfunction("arg1",App.ThisFunction("show"));` and myotherfunction is ---> `myotherfunction('arg1',func){ func; }` HOW?????????????????????? – Mostafa Aug 08 '18 at 08:38
  • This is good example. In case someone wonder what which execute first, when you pass the function with parenthesis, you literally pass a callback, namely, the function you pass would be execute as a callback. So parent function first, then function you passed. Without parenthesis, you literally pass the result of the function to parent function, which means it have to execute the function you passed first. In this case passed function first, then parent function. – ychz Sep 27 '19 at 18:35
  • 1
    Keep in mind that if these are members of a class function binding is needed. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind – Do-do-new Feb 04 '20 at 10:52
  • @Fenton i see you said you would add a comment about passing parameters to the function but i don't see it here, how would you do that? Nevermind, the way to pass arguments for anyone else wondering is to use an arrow function, for example `addContact(entityId, () => refreshContactList(arguments go here))` – Darcy Power Dec 03 '22 at 09:34
  • 1
    @DarcyPower the example is under the comment `// You can also pass arguments if you need to` – Fenton Dec 04 '22 at 18:48
525

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"]); 
dallin
  • 8,775
  • 2
  • 36
  • 41
  • 109
    this should be ranked higher as he also addresses how to pass a function with arguments – deltanine Aug 27 '14 at 03:16
  • 5
    And something I will add to this is that this feature alone - being able to pass JavaScript functions as arguments or variables or the like - is *the feature* that makes JavaScript so powerful and so great to code in. – TheHans255 Dec 09 '15 at 22:16
  • @Compynerd255 I agree, this and the ability to quickly create object literals are my two favorite aspects of Javascript. I always miss object literals in languages that don't have them. – dallin Dec 10 '15 at 22:34
  • 5
    For the "wrap it in an anonymous function" example, in case it is not obvious, the anonymous function return the function itself (with parameters) and it is invoked when it reaches the parenthesis in func(). This took me a while to figure out, so I thought it might help others. – hubpixel Apr 26 '19 at 01:07
59

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

Community
  • 1
  • 1
Gadde
  • 1,451
  • 15
  • 37
  • at first example you should add return keyword, like this: function funct(a, foo){ return foo(a) // this will return a } otherwise you will get undefined – Artem Fedotov May 20 '20 at 22:08
42

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);
Colonel Panic
  • 1,604
  • 2
  • 20
  • 31
naivists
  • 32,681
  • 5
  • 61
  • 85
19

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(); });
}
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
12

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.

Fenix Aoras
  • 221
  • 3
  • 10
8

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
Naramsim
  • 8,059
  • 6
  • 35
  • 43
6

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.

Smile
  • 2,770
  • 4
  • 35
  • 57
  • Before using eval() in production code research the security implications. Many devs simply avoid it, myself included. eval === evil is my mnemonic. – davidjmcclelland Sep 17 '21 at 15:18
3

Here it's another approach :

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

a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world     
cochon
  • 31
  • 2
3

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)
    });
Biletbak.com
  • 409
  • 5
  • 14
3

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

Victor
  • 868
  • 1
  • 9
  • 24
1

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);
}
sumit
  • 15,003
  • 12
  • 69
  • 110
1

By using ES6:


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


invoke(()=>{
  console.log("Hello World");
})
0

If you can pass your whole function as string, this code may help you.

convertToFunc( "runThis('Micheal')" )

function convertToFunc( str) {    
  new Function( str )()
 } 
function runThis( name ){
    console.log("Hello", name) // prints Hello Micheal
 }
Akin Zeman
  • 447
  • 7
  • 9
0
// Go through this code and try to understand what I have done.
var hello=(name)=>
{
    console.log("Hello",name);
}
let loadScript =(src,callback,name )=>
{
let script = document.createElement('script');
script.src=src;

script.onload = function()
{
    console.log("Script Loaded");
}
document.body.appendChild(script);
setTimeout(function()
{
    callback(name);
    // console.log("hii");
},2000);
}
setTimeout(`loadScript("https://cdn.jsdelivr.net/npm/es-module-shims@1/dist/es-module-shims.min.js",hello,"Gaurav")`,5000);
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 21 '23 at 09:52
-2

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);
}
gazgas
  • 246
  • 3
  • 7