116

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.

4
  • 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. Commented Sep 9, 2011 at 17:19
  • 1
    @xantos for example fancybox: github.com/vanntastic/fancy-box/blob/master/jquery.fancybox/… Commented Sep 9, 2011 at 17:22
  • 2
    Smashing Magazine article using this for jquery plugin boilterplate: coding.smashingmagazine.com/2011/10/11/… Commented Oct 11, 2011 at 15:24
  • @ZachL. I really liked that article. Thanks! Commented Oct 21, 2011 at 18:15

4 Answers 4

184

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...})()
Sign up to request clarification or add additional context in comments.

5 Comments

Well, why should I prefer the semicolon in front of the self-invoking function rather than after it?
@7elephant 2 semi-colons don't hurt, but no semi-colons do, so it's a safety issue, especially relevant for larger projects
preventative medicine
Do you also include a semicolon at the beginning of each statement in case the previous statement doesn't end with one?
@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.
32

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 () { ... })()

7 Comments

that is only when minified badly
@Neal, could you please explain. I think minification is entirely orthogonal to this.
@Neal It's equivalent otherwise too: try replacing ... with return 1 then add the semi-colon after 42 and see the difference.
Very interesting. I created a fiddle for what @Josh said so I could see for myself what happens: http://jsfiddle.net/LK63x/.
@Neal, Yeah. The newlines have nothing to do with it as shown by jsfiddle.net/vZvfG . Newlines only affect restricted productions in JS: return, this, ++, --, break, continue.
|
16

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.

19 Comments

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 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.
@pst, "undefined" === typeof (function () { return /*newline*/ 42; })() is true precisely because a semicolon is inserted after the return.
Re "ick - side-effects in expressions?", people who write a lot of bash tend to produce JS that looks like bash :)
@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.
|
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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.