The IIFE similarly looks like it is passed as a callback to some function that returns a function.
No. In
f(1)
there is only one function call: f
is called directly.
In
// v v function call operator
(f)(1)
// ^ ^ grouping
there is still only one function call. The code is equivalent to f(1)
; just some redundant parens were added.
We're not limited to calling variables. We can use any expression we want (as long as it evaluates to a function):
(function (x) { ... })(1)
// equivalent to:
let f = function (x) { ... };
f(1);
// but without needing a temporary variable
The only reason we can't just write function () { ... }()
is that the function
keyword cannot appear at the beginning of a statement (if it does, it is parsed as the beginning of a function declaration instead, not a function expression). But e.g.
void function () { console.log("hello"); }();
console.log( function (x) { return x + 1; }(1) );
are perfectly valid statements (containing IIFEs).
The situation is slightly different with =>
functions. Here we only have to worry about how far to the right the function body extends.
(() => console.log("hello"))();
... needs parens around the function expression because otherwise the ()
at the end would be parsed as part of the function body: console.log("hello")()
, which would try to call the value returned from console.log
.