1

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?

Zach Smith
  • 8,458
  • 13
  • 59
  • 133
  • `setTimeout(function() {alert(1)}, 1000)` Nothing on this is an IIFE – Abana Clara Sep 26 '18 at 06:19
  • `The IIFE looks like it is passed as a callback to some function that returns a function.` that description matches neither of your examples. An IIFE is an *immediately invoked function expression*. The first example is an IIFE since...you execute it immediately. But you don't pass it anywhere. The second example doesn't have an IIFE. Quite simply an IIFE is more or less defining `myFynction(a) { return a+1 }` followed by executing it `myFunction(2) //returns 3` but all in one go, instead of two lines. – VLAZ Sep 26 '18 at 06:21
  • Possibly useful resources: https://stackoverflow.com/questions/9053842/advanced-javascript-why-is-this-function-wrapped-in-parentheses https://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript – VLAZ Sep 26 '18 at 06:24

1 Answers1

3

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.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • `just some redundant parens were added.` redundant in this case, perhaps, but it's not redundant in the general case. It's to 1. be explicit it's an IIFE and 2. to prevent an unwrapped IIFE from some unintuitive parsing. – VLAZ Sep 26 '18 at 06:41
  • 1
    @vlaz It's not redundant if `function` would appear at the beginning of a statement. Otherwise it is redundant. – melpomene Sep 26 '18 at 06:51
  • Which means it's not redundant in the general case. Also, `a = function(){}()` can be really hard to understand depending on the length of the function so you might *assume* `a` is a function but in reality it's the value of an IIFE. "*As a rule of thumb, while writing unambiguous code might be technically necessary to keep the JavaScript parser from throwing SyntaxError exceptions, writing unambiguous code is also fairly necessary to keep other developers from throwing “WTFError” exceptions at you!*" [from here](http://benalman.com/news/2010/11/immediately-invoked-function-expression/) – VLAZ Sep 26 '18 at 07:02
  • binary operators may be used instead of parenthesis as well. so for example !function(){}() can be used as well. – Markus Dresch Sep 26 '18 at 07:04
  • So there is nothing special about an IIFE then... thanks – Zach Smith Sep 26 '18 at 07:12
  • 1
    @vlaz True, but that's just a matter of convention, not hard language rules. You have to know which conventions the author of the code uses because nothing prevents me from writing `a = (function () { ... });` either, which (despite parens) is not an IIFE. – melpomene Sep 26 '18 at 18:39