Immediately Invoked Function Expression: Where to put the parenthesis?
Asked Answered
D

1

7

I've seen IIFE's written:

(function() {
    console.log("do cool stuff");
})();

as well as:

(function() {
    console.log("do more cool stuff");
}());

They seem to work the same in any context I've used them, though in cases I've been told one way is right and the other is wrong, vice versa. Does anyone have any solid reason or logic as to it being written one order over the other? Is there some cases where there could be potentially more going on after the function body closes but before the invoking parenthesis come into play, or after but before that final closing parenthesis? I've mostly used these in an Angular module closures and can't seem to find anything on any real reason to go one way or the other, wondering if anyone had different experience.

Distinguishing answered 5/7, 2016 at 3:56 Comment(1)
It does not matter. "I've been told one way is right and the other is wrong, vice versa" --- this is just a matter of taste.Buchan
H
9

Short answer: It doesn't matter, as long as you put them there.

Long answer: It doesn't matter except in the case of arrow functions, because for JavaScript the only important thing is that they are there. The reason for this is that the language spec defines that a statement must only start with the function keyword if you declare a named function. Hence, it is against the spec to define an IIFE like that:

function () {}();

The workaround for this is to wrap the entire thing in parentheses, so that the statement does not start with the function keyword anymore. You achieve this by using

(function () {})();

as well as by using:

(function () {}());

Which one you choose is completely arbitrary and hence up to you.

I (personally) put the parentheses around the function, not around the call, i.e. like this one:

(function () {})();

Reason: I want to use the smallest portion of code to be wrapped in something that is only needed for technical reasons, and this is the function definition, not the call. Apart from that the spec says that you can not define a function in that way, it is not about calling the function. Hence, I think it's more clear if you wrap the definition, not the call.

edit However, in the case of the arrow function in es6, the invocation must be outside of the wrapper. It being inside the wrapper causes an unexpected token error on the opening parenthesis of the invocation. Not totally clear on the mechanics of why this is so.

Hundredweight answered 5/7, 2016 at 3:59 Comment(8)
... and a long answer?Buchan
My thoughts exactly, haha, would love a long answer.Distinguishing
Added, I had clicked Save too early. Sorry for that :-(Hundredweight
"a line of code must only start" --- not a line, but a statement. It physically may be not the beginning of the line.Buchan
Also, it may be beneficial to mention ~function() {}() or !function() {}() just as a demonstration of the idea.Buchan
What do you mean by ~function() {}() or !function() {}()Distinguishing
@AndrewClavin instead of wrapping it in parentheses you can use ~function() {}() or prefixed with !. Either turns a declaration into an expression. And all they would behave the same.Buchan
Oh that's cool, they return true and -1 instead of undefined, found + and - work too but they return NaN @BuchanDistinguishing

© 2022 - 2024 — McMap. All rights reserved.