Looking at an example of a simple IIFE
((x) => x)(1) // returns 1
If I were to think of this in terms of a regular (but anonymous) function that could be passed as a callback:
setTimeout(function() {alert(1)}, 1000)
The anonymous function is still being invoked. The IIFE similarly looks like it is passed as a callback to some function that returns a function.
It looks like this returned function is then invoked with an argument of 1
, and then the IIFE is invoked by the function returned by some function
Is this correct? What object is some function defined on? Is it window/global? Or is this a JavaScript implementation feature and not a language feature?
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
.