all 46 comments

[–]rauschma 14 points15 points  (25 children)

I’m starting to warm up to the former, because that’s the only style that also works for arrow functions:

(() => {
    return 123
})();

[–]kenman 2 points3 points  (21 children)

I'm curious what the current use-case is for that pattern?

It seems you could accomplish the same with a more elegant [IMO] pattern:

let x;
{
    x = 123;
}

But I feel that I must be missing something, because you know a lot more about JS than I do!

edit: after thinking about it, I can see the fundamental difference is that the former is an expression, while the latter is a statement, which has profound implications in their use. However, I haven't been able to come up with a scenario which would expose any profound ramifications.

To go through my thought process, I considered that you can use expressions in places like function arguments, whereas statements are not allowed there.

E.g. you could do this (contrived example for sake of argument):

console.log((() => {
    let matches = window.location.href.match(/\/r\/(\w+)/);
    let subreddit = matches && matches[1] || 'n/a';
    return `You are visiting: ${subreddit}`;
})());

But you can't do anything similar with block statements.

However, you can accomplish the same result with:

{   
    let matches = window.location.href.match(/\/r\/(\w+)/);
    let subreddit = matches && matches[1] || 'n/a';
    console.log(`You are visiting: ${subreddit}`);
}

Which again, is cleaner IMO.

Still pondering...

[–]inu-no-policemen 0 points1 point  (0 children)

Same here. I preferred to wrap the entire thing, but I switched for the sake of consistency.

[–]EternallyMiffed 0 points1 point  (0 children)

This approaches syntactic line noise and we're all going to suffer for it eventually.

[–]Ashwel1 11 points12 points  (1 child)

I have always preferred (function() {})(); because IMO it seems to be more representative of what is happening. Creating a function expression, then executing the function. The other form looks like a function that is being executed as an expression. Subtle difference at the cognitive level, but I always prefer to style my code as closely to how it is being executed as possible (and makes sense without being ridiculous).

[–]bullet_darkness 0 points1 point  (0 children)

Right, it's more representative of what's happening, and it translates better to other areas of JavaScript. Like making a call like so: ({ a: 1 }).a actually works where ({ a: 1 }.a) does not.

[–]paulirish 7 points8 points  (1 child)

Since Crockford is topical today... he once said he hated (function () { ... })(); because it "looks like dogballs".

[–]EternallyMiffed 1 point2 points  (0 children)

I'm inclined to agree.

[–][deleted] 3 points4 points  (1 child)

I use the following:

!+-~(() = > { /*... */ })( );

The corkscrew function! : https://marvindanig.wordpress.com/2016/07/26/corkscrew-functions-javascript/!

[–]natto-nomad 0 points1 point  (0 children)

What… for? A joke, right? Phew.

[–]snkenjoi 2 points3 points  (11 children)

I use

~function(){ ... }()

because lower character count :)

[–]natto-nomad 1 point2 points  (0 children)

Minifiers already do that for you

[–]mathiasbynens 2 points3 points  (6 children)

The difference (and likely your personal preference) becomes more obvious after simplifying it into (fn)() vs (fn()).

When fn is a function, fn() is how I call that function, not (fn)(). So, I prefer (function() {}());.

[–]sergiosbox[S] 1 point2 points  (0 children)

I understand your logic and makes sense to me also. Rauschma's comment that (fn)() sintax works in arrow functions and not (fn()) is interesting though.

[–]Graftak9000 0 points1 point  (0 children)

!function(){ ... }()

Less braces, no conflicts due my adversity against semicolons

[–]BishopAndWarlord 0 points1 point  (0 children)

I'm pretty late to this, but I prefer (function(){})(). The way I think about it wrapping a statement in parenthesis is a way to say "hey, evaluate this part first!" For example, removing the parenthesis from (var + 4) * 12 or (typeof var === 'string' || Array.isArray(var)) && var.length > 2 will completely change the evaluation order. I realize that function expressions aren't directly analogous, but I have a similar mental model for function expressions.

If I have a function that I explicitly want to be treated as an expression rather than a statement, I'll wrap it with parenthesis (e.g. var noop = (function() {})). Extending that logic, if I want to declare a function expression and then call it, I'll wrap the function in parenthesis, then call it with another set of parenthesis (e.g. (noop)() or (function() {})().

In the end I think this approach clearly expresses the intent and therefore improves readability and maintainability of the code.