107

What is the benefit of using semicolon before a self-invoking function in JavaScript? I saw this approach in few popular jQuery plugins and I'm curious to find if this is the next awesome thing in JavaScript that I don't know.

Usama Abdulrehman
  • 1,106
  • 3
  • 9
  • 20
7elephant
  • 2,531
  • 5
  • 18
  • 17
  • 2
    The semi-colon is placed in front of the left paren `(` in order to prevent the JavaScript interpreter from interpreting the parens as a function invocation operator. – Šime Vidas Sep 09 '11 at 17:19
  • 1
    @xantos for example fancybox: https://github.com/vanntastic/fancy-box/blob/master/jquery.fancybox/jquery.fancybox-1.2.1.js – 7elephant Sep 09 '11 at 17:22
  • 2
    Smashing Magazine article using this for jquery plugin boilterplate: http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/ – Zach Lysobey Oct 11 '11 at 15:24
  • @ZachL. I really liked that article. Thanks! – 7elephant Oct 21 '11 at 18:15

4 Answers4

174

If you concatenate two files with self-invoking functions together that look like this:

File A:

(function(){...A...})()

File B:

(function(){...B...})()

File A+B:

(function(){...A...})()(function(){...B...})()

You have two statements without separator. This happens when you cat files together and then minify them.

Now the author of file B puts a semicolon in front:

File B2:

;(function(){...B2...})()

And you'll get a working script:

(function(){...A...})();(function(){...B2...})()
amoebe
  • 4,229
  • 4
  • 34
  • 38
  • 19
    Well, why should I prefer the semicolon in front of the self-invoking function rather than after it? – 7elephant Sep 09 '11 at 17:24
  • 36
    @7elephant 2 semi-colons don't hurt, but no semi-colons do, so it's a safety issue, especially relevant for larger projects – fncomp Sep 09 '11 at 17:27
  • 15
    preventative medicine – Jason S Sep 09 '11 at 17:27
  • 8
    Do you also include a semicolon at the beginning of each statement in case the previous statement doesn't end with one? – Brandon Gano Mar 27 '15 at 23:43
  • 4
    @Brandon No, only in front of the whole file. The statements inside the concatenated files should be separated by semicolons anyway to create valid JavaScript code. – amoebe Apr 03 '15 at 19:37
30

Self-invoking functions are surrounded by parentheses, and in JavaScript parentheses are overloaded to mean

  1. Grouping expressions to override precedence: (x + y) * z
  2. Function application : f()

Putting a semicolon before the function prevents the function from becoming an argument to whatever precedes it when the parentheses become confused with function application.

Consider

var x = 42

(function () { ... })()

is the same as

var x = 42(function () { ... })()

but

var x = 42

;

(function () { ... })()

is the same as

var x = 42;

(function () { ... })()
Mike Samuel
  • 109,453
  • 27
  • 204
  • 234
  • 2
    that is only when minified badly – Naftali aka Neal Sep 09 '11 at 17:19
  • @Neal, could you please explain. I think minification is entirely orthogonal to this. – Mike Samuel Sep 09 '11 at 17:22
  • 2
    @Neal It's equivalent otherwise too: try replacing `...` with `return 1` then add the semi-colon after 42 and see the difference. – fncomp Sep 09 '11 at 17:23
  • Very interesting. I created a fiddle for what @Josh said so I could see for myself what happens: [http://jsfiddle.net/LK63x/](http://jsfiddle.net/LK63x/). – bittersweetryan Sep 09 '11 at 17:28
  • @Neal, Yeah. The newlines have nothing to do with it as shown by http://jsfiddle.net/vZvfG/ . Newlines only affect [restricted productions](http://aresemicolonsnecessaryinjavascript.com/) in JS: `return`, `this`, `++`, `--`, `break`, `continue`. – Mike Samuel Sep 09 '11 at 17:30
  • +1 though not all IIFEs are necessarily surrounded by parentheses. `!function(){}()` or `"invoke!",function(){}()` would work as well and would only need the preceding `;` if the code gets minified. – user113716 Sep 09 '11 at 17:46
  • @patrick dw, Interesting. I haven't seen that pattern in production code. – Mike Samuel Sep 09 '11 at 17:51
15

I write all JavaScript in a semicolon-free style. When writing without semicolons at the end of every line, due to Automatic Semicolon Insertion (ASI), there are a few special cases that can "be confusing" at first:

  1. Starting a top-level expression with an operator, a ( (open parenthesis) in this case, which like most other operators, can continue the previous expression and thus suppresses the "automatic insertion of a semicolon". (This generally only occurs when using a self invoking function.)

  2. Just kidding about #2: there isn't one! (Learn only one rule and you too can enjoy life without extra semicolons ;-)

Since I write in a semicolon-free style I thus always write it as (where the function-expression can naturally span multiple lines):

;(FunctionExpression)()

In my case it isn't about "safety" or trying to "catch an error" (honestly, if your style is to use semi-colons and you forget a semi-colon, then you've already created the error elsewhere and writing a ; at the start for "safety" is hogwash). No; in my case it is done for consistency with knowledge of my chosen style and "knowing" that starting a line with an operator can continue an expression from a previous line.

See JavaScript: Semicolon Insertion (Everything You Need To Know) for the details (it is by far the best article I have seen on the subject).

Happy coding.

  • 10
    You're asking for trouble, really, relying on what is essentially an mechanism to gloss over sloppy programming. The semicolons are there for a reason. – thepeer Feb 05 '13 at 15:07
  • 6
    @thepeer No, no, I'm not really. Omitting semi-colons is not "sloppy coding". Please back up such unfounded claims; in my post I have explained what the "issue" is when writing in a semicolon-free style and provided a rule on how to write code that *never* has a problem with ASI. Then I explain why it is irrelevant to "safety" and provide a link to a resource covering the details (look up the `return` production in the link). On the other hand, the comment that provoked this response attacked my coding style and made a statement which I find to be unfounded. Not cool. –  Feb 05 '13 at 17:02
  • @thepeer While I have addressed different "safety" concerns in other questions about ASI, in this particular answer I make the claim that it is *incorrect and unsafe* to omit *any* semi-colon in a semicolon-required style - particularly because one is not *always* prepared for continued lines, as one (like me) who writes a semicolon-free style is. Thus there is no difference between the two approaches in terms of "safety". Now, the big *advantage* of semicolons is that many tools/formatters are confused if such are not used. This is *not* related to "sloppy coding", but relates to tooling. –  Feb 05 '13 at 17:10
  • @thepeer As for a real-world numbers on terms of the "safety" in code, I have only my own experience. In many, many years of JavaScript, I have been burnt by a semicolon-free code exactly once when I first ran into this construct. I have had *none* relating to semicolon "omission" since I started using rule #1 - that's pretty impressive, no? (I have been burnt by the `return` construct a few times but, ironically, that is *not* related to writing in a semicolon-free style. See the link in the article.) –  Feb 05 '13 at 17:15
  • There are other rules. For example, `"undefined" === typeof (function () { return /*newline*/ 42; })()`. See [restricted productions](http://es5.github.com/#x7.9.1) for more details. – Mike Samuel Feb 05 '13 at 18:03
  • @MikeSamuel Thanks for writing it out :) That production is covered in the linked article and is just as broken with/without the semicolon. It's an interesting production grammar itself and runs counter to the `;`-ends a statement view. –  Feb 05 '13 at 18:05
  • @pst, Restricted productions are not covered in your rule 1. You need a rule 2. – Mike Samuel Feb 05 '13 at 18:06
  • @MikeSamuel No, I do not. It is *unrelated* to semicolons. One needs to "know" that even if ending every statement with a semicolon. As such, it is a flawed argument that rule #1 doesn't cover it. –  Feb 05 '13 at 18:07
  • @pst, `"undefined" === typeof (function () { return /*newline*/ 42; })()` is true precisely because a semicolon is inserted after the `return`. – Mike Samuel Feb 05 '13 at 18:08
  • @MikeSamuel Oh, I see what's confusing. I'm was intending that rule to cover the case of writing semicolon-free code for code that was *otherwise valid* with semicolons. In any case, this is well covered in the supplied resource - I keep saying it because it's a good read and will cover more than an SO answer is intended to - and is just as invalid with a semicolon. –  Feb 05 '13 at 18:09
  • @pst, Here's another case : if you tend to write shorthand like `condition && side_effect()` then `/foo/i.test(x) && sideEffect()` following `var x = 42` turns into the equivalent of `var x = 42 / foo / i.test(x) && sideEffect()`, so top level regular expressions are also problematic since they can be ambiguous with division operators. – Mike Samuel Feb 05 '13 at 18:11
  • @pst, Fair enough re restricted productions. – Mike Samuel Feb 05 '13 at 18:12
  • @MikeSamuel Touche. I guess I just "take binary operators for granted" :D (That regex case is extra tricky, but ick - side-effects in expressions? :-/) –  Feb 05 '13 at 18:12
  • @pst, Yeah. `(` ambiguity is a grammar level ambiguity, while the `/` is a lexical ambiguity. I do sympathize with your overall point -- since I started writing Go code, I've found that I appreciate some formulations of semicolon insertion. This would not be a problem with JavaScript's semicolon insertion rules applied to a language with a regular lexical grammar, but JavaScript's weird tokenization rules do lead to more corner cases. – Mike Samuel Feb 05 '13 at 18:16
  • 1
    Re "ick - side-effects in expressions?", people who write a lot of bash tend to produce JS that looks like bash :) – Mike Samuel Feb 05 '13 at 18:17
  • @MikeSamuel Touche again. I must stop before I run out of points to give. –  Feb 05 '13 at 18:18
  • 6
    @pst I wasn't accusing *you* of sloppy coding; forgive me if that's how it read. I meant that the reason why the js parser automatically inserts semicolons was originally - like some other js features (undeclared variables becoming global is another) - because js was seen as a hack-ish language that should be forgiving of sloppy coding practises. I'm aware that there is a movement to make semicolon-free js more rigorous; I'm against it. In fact I wish strict mode would throw an error or at least a warning when a semicolon is omitted. – thepeer Feb 12 '13 at 10:07
  • @user166390 Your rule 1 doesn't cover statements that begin with `[`. It's not quite so common, but something like this will also fail if you're relying on ASI: `var abc = [ 1, 2, 3, 4 ] /*newline*/ [ 'hello', 'world' ].forEach(function(it) { console.log(it) })` – user2221343 Aug 25 '16 at 15:38
3

For me, the semi colon was triggering an error in Internet Explorer 8 (or at least that's what IETester said), and preventing the ui tabs from working properly.

The error message was Invalid character in jquery.all.ui.js Line: 1. Char: 1.

I stumbled on the semi-colon completely by chance. When I removed the ; from the ;(function($) it worked, seemingly without side-effects or loss of functionality. I am using Drupal, don't know whether this has anything to do with the matter.

Francis
  • 510
  • 5
  • 16