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.
-
2The 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
-
2Smashing 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 Answers
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...})()
- 4,229
- 4
- 34
- 38
-
19Well, 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
-
8Do 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
Self-invoking functions are surrounded by parentheses, and in JavaScript parentheses are overloaded to mean
- Grouping expressions to override precedence:
(x + y) * z
- 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 () { ... })()
- 109,453
- 27
- 204
- 234
-
2
-
@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
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:
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.)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.
-
10You'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
-
-
@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
-
1Re "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
-
-
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
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.
- 510
- 5
- 16