[javascript] Functions that return a function

I'm stuck with this concept of 'Functions that return functions'. I'm referring the book 'Object Oriented Javascript' by Stoyan Stefanov.

Snippet One:

_x000D_
_x000D_
    function a() {_x000D_
      _x000D_
        alert('A!');_x000D_
    _x000D_
        function b(){_x000D_
            alert('B!'); _x000D_
        }_x000D_
    _x000D_
        return b();_x000D_
    }_x000D_
    _x000D_
    var s = a();_x000D_
    alert('break');_x000D_
    s();
_x000D_
_x000D_
_x000D_

Output:

A!
B!
break

Snippet Two

_x000D_
_x000D_
function a() {_x000D_
  _x000D_
    alert('A!');_x000D_
_x000D_
    function b(){_x000D_
        alert('B!'); _x000D_
    }_x000D_
_x000D_
    return b;_x000D_
}_x000D_
_x000D_
var s = a();_x000D_
alert('break');_x000D_
s();
_x000D_
_x000D_
_x000D_ Output:

A!
break
B!

Can someone please tell me the difference between returning b and b() in the above snippets?

This question is related to javascript

The answer is


This is super useful in real life.

Working with Express.js

So your regular express route looks like this:

function itWorksHandler( req, res, next ) {
  res.send("It works!");
}

router.get("/check/works", itWorksHandler );

But what if you need to add some wrapper, error handler or smth?

Then you invoke your function off a wrapper.

function loggingWrapper( req, res, next, yourFunction ) {
  try {
    yourFunction( req, res );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", function( req, res, next ) {
  loggingWrapper( req, res, next, itWorksHandler );
});

Looks complicated? Well, how about this:

function function loggingWrapper( yourFunction ) => ( req, res, next ) {
  try {
    yourFunction( req, res, next );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", loggingWrapper( itWorksHandler ) );

See at the end you're passing a function loggingWrapper having one argument as another function itWorksHandler, and your loggingWrapper returns a new function which takes req, res, next as arguments.


Imagine the function as a type, like an int. You can return ints in a function. You can return functions too, they are object of type "function".

Now the syntax problem: because functions returns values, how can you return a function and not it's returning value?

by omitting brackets! Because without brackets, the function won't be executed! So:

return b;

Will return the "function" (imagine it like if you are returning a number), while:

return b();

First executes the function then return the value obtained by executing it, it's a big difference!


return b(); calls the function b(), and returns its result.

return b; returns a reference to the function b, which you can store in a variable to call later.


Assigning a variable to a function (without the parenthesis) copies the reference to the function. Putting the parenthesis at the end of a function name, calls the function, returning the functions return value.

Demo

function a() {
    alert('A');
}
//alerts 'A', returns undefined

function b() {
    alert('B');
    return a;
}
//alerts 'B', returns function a

function c() {
    alert('C');
    return a();
}
//alerts 'C', alerts 'A', returns undefined

alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());

In your example, you are also defining functions within a function. Such as:

function d() {
    function e() {
        alert('E');
    }
    return e;
}
d()();
//alerts 'E'

The function is still callable. It still exists. This is used in JavaScript all the time. Functions can be passed around just like other values. Consider the following:

function counter() {
    var count = 0;
    return function() {
        alert(count++);
    }
}
var count = counter();
count();
count();
count();

The function count can keep the variables that were defined outside of it. This is called a closure. It's also used a lot in JavaScript.


When you return b, it is just a reference to function b, but not being executed at this time.

When you return b(), you're executing the function and returning its value.

Try alerting typeof(s) in your examples. Snippet b will give you 'function'. What will snippet a give you?


Returning b is returning a function object. In Javascript, functions are just objects, like any other object. If you find that not helpful, just replace the word "object" with "thing". You can return any object from a function. You can return a true/false value. An integer (1,2,3,4...). You can return a string. You can return a complex object with multiple properties. And you can return a function. a function is just a thing.

In your case, returning b returns the thing, the thing is a callable function. Returning b() returns the value returned by the callable function.

Consider this code:

function b() {
   return 42;
}

Using the above definition, return b(); returns the value 42. On the other hand return b; returns a function, that itself returns the value of 42. They are two different things.


Create a variable:

var thing1 = undefined;

Declare a Function:

function something1 () {
    return "Hi there, I'm number 1!";
}

Alert the value of thing1 (our first variable):

alert(thing1); // Outputs: "undefined".

Now, if we wanted thing1 to be a reference to the function something1, meaning it would be the same thing as our created function, we would do:

thing1 = something1;

However, if we wanted the return value of the function then we must assign it the return value of the executed function. You execute the function by using parenthesis:

thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!" 

Snippet one:

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b(); //return nothing here as b not defined a return value
}

var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain

the statement 'b()' means to execute the function named 'b' which shows a dialog box with text 'B!'

the statement 'return b();' means to execute a function named 'b' and then return what function 'b' return. but 'b' returns nothing, then this statement 'return b()' returns nothing either. If b() return a number, then ‘return b()’ is a number too.

Now ‘s’ is assigned the value of what 'a()' return, which returns 'b()', which is nothing, so 's' is nothing (in JavaScript it’s a thing actually, it's an 'undefined'. So when you ask JavaScript to interpret what data type the 's' is, JavaScript interpreter will tell you 's' is an undefined.) As 's' is an undefined, when you ask JavaScript to execute this statement 's()', you're asking JavaScript to execute a function named as 's', but 's' here is an 'undefined', not a function, so JavaScript will complain, "hey, s is not a function, I don't know how to do with this s", then a "Uncaught TypeError: s is not a function" error message will be shown by JavaScript (tested in Firefox and Chrome)


Snippet Two

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b; //return pointer to function b here
}

var s = a();  //s get the value of pointer to b
alert('break');
s(); // b() function is executed

now, function 'a' returning a pointer/alias to a function named 'b'. so when execute 's=a()', 's' will get a value pointing to b, i.e. 's' is an alias of 'b' now, calling 's' equals calling 'b'. i.e. 's' is a function now. Execute 's()' means to run function 'b' (same as executing 'b()'), a dialog box showing 'B!' will appeared (i.e. running the 'alert('B!'); statement in the function 'b')


Returning the function name without () returns a reference to the function, which can be assigned as you've done with var s = a(). s now contains a reference to the function b(), and calling s() is functionally equivalent to calling b().

// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;

Calling the function with () in a return statement executes the function, and returns whatever value was returned by the function. It is similar to calling var x = b();, but instead of assigning the return value of b() you are returning it from the calling function a(). If the function b() itself does not return a value, the call returns undefined after whatever other work is done by b().

// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;