70

I want to write my own function in JavaScript which takes a callback method as a parameter and executes it after the completion, I don't know how to invoke a method in my method which is passed as an argument. Like Reflection.

example code

function myfunction(param1, callbackfunction)
{
    //do processing here
    //how to invoke callbackfunction at this point?
}

//this is the function call to myfunction
myfunction("hello", function(){
   //call back method implementation here
});
Muhammad Ummar
  • 3,426
  • 4
  • 36
  • 68

8 Answers8

100

You can just call it as a normal function:

function myfunction(param1, callbackfunction)
{
    //do processing here
    callbackfunction();
}

The only extra thing is to mention context. If you want to be able to use the this keyword within your callback, you'll have to assign it. This is frequently desirable behaviour. For instance:

function myfunction(param1, callbackfunction)
{
    //do processing here
    callbackfunction.call(param1);
}

In the callback, you can now access param1 as this. See Function.call.

lonesomeday
  • 215,182
  • 48
  • 300
  • 305
  • What if I want to pass in an argument to the callback function when myfunction is called? For example, `myfunction("hello", function(arg1) { console.log(arg1); })` – Ashley Wilson May 15 '20 at 04:59
  • @AshleyWilson same thing applies. You just need to make sure that the function is called with argument, without the call. ex: `callbackfunction(param1)`. – Chen Li Yong Jun 30 '20 at 03:49
5

I too came into same scenario where I have to call the function sent as parameter to another function.

I Tried

mainfunction('callThisFunction');

First Approach

function mainFuntion(functionName)
{
    functionName();
}

But ends up in errors. So I tried

Second Approach

functionName.call(). 

Still no use. So I tried

Third Approach

this[functionName]();

which worked like a champ. So This is to just add one more way of calling. May be there may be problem with my First and Second approaches, but instead googling more and spending time I went for Third Approach.

Kiran
  • 977
  • 1
  • 16
  • 28
  • 5
    The first two approaches work if you pass the function as a parameter like this mainfunction(callThisFunction); and not as a String. But anyway yes, you have there a 3rd approach :) – pedromendessk Apr 27 '15 at 13:38
2
function myfunction(param1, callbackfunction)
{
    //do processing here
   callbackfunction(); // or if you want scoped call, callbackfunction.call(scope)
}
Roki
  • 2,630
  • 20
  • 21
  • will you please tell me more about scoped call? – Muhammad Ummar May 14 '11 at 10:19
  • 1
    @Ummar: "Scoped" in the wrong term, @Roki is talking about what the `this` value within the call will be. You can explicitly determine what `this` is within `callbackfunction` by using `call` (or `apply`). It's nothing to do with scope, though. The usual term is "context" (e.g., setting the context of the call). – T.J. Crowder May 14 '11 at 10:23
  • T.J. has right. the execution "context" by default in global functions is window but if you want to change that you can call the function with different object. – Roki May 14 '11 at 10:26
1

object[functionName]();

object: refers to the name of the object.

functionName: is a variable whose value we will use to call a function.

by putting the variable used to refer to the function name inside the [] and the () outside the bracket we can dynamically call the object's function using the variable. Dot notation does not work because it thinks that 'functionName' is the actual name of the function and not the value that 'functionName' holds. This drove me crazy for a little bit, until I came across this site. I am glad stackoverflow.com exists <3

Vaibhav Mule
  • 4,447
  • 3
  • 31
  • 51
Moises D
  • 11
  • 1
  • 1
    This is a useful technique, but is it relevant to the question? There is a function object being passed, not a method name... – Davis Herring Sep 21 '17 at 03:03
0

I will do something like this

var callbackfunction = function(param1, param2){
console.log(param1 + ' ' + param2)
}

myfunction = function(_function, _params){
_function(_params['firstParam'], _params['secondParam']);
}

Into the main code block, It is possible pass parameters

myfunction(callbackfunction, {firstParam: 'hello', secondParam: 'good bye'});
jcromeros1987
  • 137
  • 1
  • 4
0

All the examples here seem to show how to declare it, but not how to use it. I think that's also why @Kiran had so many issues.

The trick is to declare the function which uses a callback:

function doThisFirst(someParameter,  myCallbackFunction) {
    // Do stuff first
    alert('Doing stuff...');

    // Now call the function passed in
    myCallbackFunction(someParameter);
}

The someParameter bit can be omitted if not required.

You can then use the callback as follows:

doThisFirst(1, myOtherFunction1);
doThisFirst(2, myOtherFunction2);

function myOtherFunction1(inputParam) {
    alert('myOtherFunction1: ' + inputParam);
}

function myOtherFunction2(inputParam) {
    alert('myOtherFunction2: ' + inputParam);
}

Note how the callback function is passed in and declared without quotes or brackets.

  • If you use doThisFirst(1, 'myOtherFunction1'); it will fail.
  • If you use doThisFirst(1, myOtherFunction3()); (I know there's no parameter input in this case) then it will call myOtherFunction3 first so you get unintended side effects.
SharpC
  • 5,368
  • 3
  • 37
  • 36
0

Another way is to declare your function as anonymous function and save it in a variable:

var aFunction = function () {
};

After that you can pass aFunction as argument myfunction and call it normally.

function myfunction(callbackfunction) {
    callbackfunction();
}

myfunction(aFunction);

However, as other answers have pointed out, is not necessary, since you can directly use the function name. I will keep the answer as is, because of the discussion that follows in the comments.

stivlo
  • 77,013
  • 31
  • 135
  • 193
  • 1
    This question is about how `myfunction` can *call* the callback being passed into it, not about calling `myfunction` *as* a callback. But even if it were, there's no reason whatsoever for making the function anonymous. You can use the symbol `myfunction` to refer to the function either way. (And making it anonymous [keeps your tools from helping you](http://blog.niftysnippets.org/2010/03/anonymouses-anonymous.html).) – T.J. Crowder May 14 '11 at 10:21
  • Ok, I've edited the question to swap the names, I'm reading your article, thanks for the pointer. – stivlo May 14 '11 at 10:38
  • Again: You don't need the `callbackfunction` function to be anonymous in order to use it as a callback. (It *can* be if you like, but it doesn't need to be.) Your answer still gives the strong impression that it does. It also uses two different `callbackfunction` symbols (one of them a variable, the other a function argument) which is confusing. – T.J. Crowder May 14 '11 at 10:49
  • @T.J. Crowder I got your point about anonymous functions, I'm not going to change that in my answer though, because there are already other answers showing the other way. It has been downvoted so it stays down, I'm fine with that. Very interesting your article about how to organize JavaScript classes also allowing private methods. I'll try it in my code. – stivlo May 14 '11 at 10:59
  • I've added some comments that is an alternative way and pointed to the discussion here in the comments, so now should be clearer. – stivlo May 14 '11 at 11:05
0

Super basic implementation for my use case based on some excellent answers and resources above:

/** Returns the name of type member in a type-safe manner. **(UNTESTED)** e.g.:
*
* ```typescript
* nameof<Apple>(apple => apple.colour); // Returns 'colour'
* nameof<Apple>(x => x.colour); // Returns 'colour'
* ```
*/
export function nameof<T>(func?: (obj: T) => any): string {
 const lambda = ' => ';
 const funcStr = func.toString();

 const indexOfLambda = funcStr.indexOf(lambda);
 const member = funcStr.replace(funcStr.substring(0, indexOfLambda) + '.', '').replace(funcStr.substring(0, indexOfLambda) + lambda, '');

 return member;
}
Ross
  • 1,816
  • 2
  • 23
  • 34