简体   繁体   中英

Passing function as callback without argument - need help to understand it

I've seen a code sample like that in some tutorial:

getSomething(function onSomething(name) {
  return renderSomething(name);
});

And that it is equal to the following:

getSomething(renderSomething);

I'm a newbie, and never seen anything like this before. I can't really understand how the above can be the same(without parameter on the renderSomething() ). I've tried to recreate something similar to the above code to better understand it and kind of failed. I'm showing you what I've tried and hopefully you can explain to me why the above is equivalent and the below two questions that came up.

Can you please explain to me:

  1. Why parameter name is undefined?
  2. How come the console.log('a') is printed before the console.log('c') ?

 var name = 'alex'; console.log('start'); function print(cb) { console.log('a'); cb(); } function renderName(name) { console.log('b'); console.log(name); } print(function onPrint(name) { console.log('name: ', name); console.log('c'); return renderName(name); });

Pass the parameter to cb in print function

 var name = 'alex'; console.log('start'); function print(cb) { console.log('a'); return cb(name); } function renderName(name) { console.log('b'); console.log(name); } print(function onPrint(name) { console.log('name: ', name); console.log('c'); return renderName(name); });

As to your questions:

Why parameter name is undefined?

Because you didn't pass an argument when you called cb() . It would have worked if for instance you had done cb("John") .

How come the console.log('a') is printed before the console.log('c') ?

Because that is the very first thing that the print function does. It only calls your callback with cb() after having done that.

To understand how those two statements are equivalent, you really need to look inside of the function and also to reflect on why we use callbacks in the first place. It's also important to understand the difference between function declarations ( function getFullName ), invocations ( getFullName() ) and references ( getFullName ).

We use callbacks to react to something that might happen later, usually the result of whatever has happened is of interest to us. So we create callbacks that receive that result.

Imagine you have a function getFullName , if it was synchronous you would just call it like this:

const fullName = getFullName('John', 'Doe');

And inside the function might simply be:

function getFullName(firstName, lastName) {
    return firstName + ' ' + lastName;
}

But for some reason, this function is asynchronous, so you don't get the result directly, so we use a callback to get notified when the name is ready to use:

function getFullName(firstName, lastName, callback) {
    // Do something that takes time, then with the result of that
    callback(firstName + ' ' + lastName);
}

Now when we call this function, it looks like this:

getFullName('John', 'Doe', function (fullName) {
    console.log(fullName);
});

So the getFullName function, will invoke our callback and pass it the value it created. Since your function takes 1 argument, the fullName will be in that argument, no matter what we name that argument. So we can replace our callback (that we've created as an anonymous function) with any other function that takes one argument, such as console.log, like this:

getFullName('John', 'Doe', console.log)

In both these cases, we're sending in a function reference to getFullName , in the first case it's a reference from a function we've just created, in the second it's a reference to a function in the global scope.

You could equally do this:

const myCallback = function(fullName) {
   console.log(fullName);
}

getFullName('John', 'Doe', myCallback);

Note how this is different from doing something like this:

getFullName('John', 'Doe', myCallback()); <-- function invocation!

Here, because we are invoking/calling the function, it will execute, and the result of that will be passed as the third argument to getFullName , which isn't what we wanted.

Reading up on first class functions might give you more insight!

As others have mentioned, but for completion, in your example, you never pass some result to your callback, in this case you could pass the variable name or something else to simulate the result being created. And by flipping the order in which you call console.log and cb(name) your logs should make sense. What you return from your callback function will never really be used, at least not in our example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM