New to callback functions (passing a callback as p

2019-08-03 21:27发布

Newbie question here.

I am trying to understand callback functions better. Reading about them here, i though i grasped the idea.

    function greeting (name, callback){
      console.log(`Greetings ${name}`);
      callback();
    };

    function timeOfDay (time){
      console.log(`How are you this fine ${time}?`);
    };

    greeting ('Brad', timeOfDay('evening') );

Output

How are you this evening?
Greetings Brad
Uncaught TypeError: callback is not a function

Can someone please explain why the output is in this order? What does this error refer to and why does it appear even though the code has finished?

I first did a simple callback function along the same structure and it worked fine.

Thanks in advance Brad

2条回答
手持菜刀,她持情操
2楼-- · 2019-08-03 21:47

You were close, but when passing timeOfDay("evening"), you aren't actually passing that function as the callback. That is a function invocation and it runs immediately and whatever the return value of that is, is what is passed to the greeting function invocation as the second argument. Since timeOfDay doesn't return anything, you are passing undefined to greeting.

The solution is to pass an actual function, not the result of invoking one (unless that result is, in fact, another function), to greeting, and one way we can do that is by wrapping the timeOfDay() function call in an anonymous function declaration, like this:

function greeting (name, callback){
  console.log(`Greetings ${name}`);
  callback();
};

function timeOfDay (time){
  console.log(`How are you this fine ${time}?`);
};

greeting ('Brad', function() { timeOfDay('evening') } );

Another technique is to use the Function.bind() method, which returns a copy of the function you've called it on, but the context that the function will execute in is configurable by you, based on the first argument you pass to .bind(). This is a very useful technique, but requires a good knowledge and understanding of scope and context, which you can read more about in another answer of mine:

function greeting (name, callback){
  console.log(`Greetings ${name}`);
  callback();
};

function timeOfDay (time){
  console.log(`How are you this fine ${time}?`);
};

greeting ('Brad', timeOfDay.bind(this,'evening') );

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-08-03 21:56

As said in the comments, when you do something like this:

greeting ('Brad', timeOfDay('evening') );

you will be calling the timeOfDay function instantaneously.

To avoid that you can use one of these options:

  1. Wrap your function call in an anonymous function, like said in another answers.

  2. You can omit/remove the parenthesis, like this greeting('Brad', timeOfDay); (this avoid instant function call, but you'll lose your parameter "evening" and the error will persist).

  3. You can .bind() a context to the function, in the example below, I'm binding this as the context to the function, that way it's not going to call the function instantaneously.

take a look:

function greeting (name, callback){
  console.log(`Greetings ${name}`);
  callback();
};

function timeOfDay (time){
  console.log(`How are you this fine ${time}?`);
};

greeting ('Brad', timeOfDay.bind(this, 'evening') );

Further reading: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

查看更多
登录 后发表回答