Semicolons matter

When your code’s intention is ambiguous, your JavaScript engine will attempt to fill in the gaps. If there are multiple potential intentions, your engine will tend to assume you meant to do the right thing. Multi-line statements are supported, omitting semicolons is not, and therefore if the case is ambiguous your engine will assume you meant to write a multi-line statement.

Take the following example:

function Logger() { }

// Log something to the console at a specified level
Logger.prototype.log = function(level) {
  console[level || 'log'].apply(console, [].slice.apply(arguments, 1));
}

// Sugar functions for Logger.log
['info', 'warn', 'error'].forEach(function(level) {
  Logger.prototype[level] = function () {
    return this.log.apply(this, [level].concat(Array.from(arguments)));
  }
});

What will happen when this is run? Did you spot the missing semicolons? Here’s a summary of how v8 sees it (I’ve removed the internals for clarity):

Logger.prototype.log = 
  function() { }['info', 'warn', 'error'].forEach(function() { });

Which is perfectly valid code; it is the rough equivalent of:

function foo() { }
Logger.prototype.log = foo['error'].forEach(function() { });

Be unambiguous with your code. If you’re ending a statement, use a semicolon.

11 thoughts on “Semicolons matter

    1. It’s missing after both inline function definitions. Without the semicolon after the definition of

      Logger.prototype.log = function(level) { }
      ['info', 'warn', 'error'].forEach()

      v8 thinks you’re writing a multi-line statement

      Logger.prototype.log = function(level) {}['info', 'warn', 'error'].forEach()
  1. Hi Ryan,
    Its a matter of code style. There are different drawbacks whenever you choose to use or not to use semicolons. I suggest using one of the popular code styles, I personally use Javascript Standard Style. There are many different options with their pros and cons. You have to choose the one that suites you the most. The best advice I can give – lint your code, use what your team is using.

  2. What is funny is that if you run this code through standard.js, it actually warns about: Unexpected newline between object and [ of property access.

    So for me, this proves that writing my code without semicolons with standard.js is actually safer option than to try put semicolons where they belong myself.

    1. I wonder why standard js does not report “missing semi”. If the people behind standard js were interested in standards they would have used any existing one.

      1. It can’t tell you that because it doesn’t know if a semi colon is missing. The compiler doesn’t know you meant to have one there, all it knows is that the opening bracket isn’t meant to be there.

  3. The no-semicolon people will tell you to add a semicolon in front of the [, instead of putting it where it should belong, in the most logical place.

  4. So… add semicolons to every single line even though the vast majority of the time they’re redundant. Or you can just add them at the front of the line in the two cases (are there more?) where they’re actually needed.

  5. Or they will tell you to do something like this:

        var logLevels = ['info', 'warn', 'error']
        
        logLevels.forEach(function(level) {
          Logger.prototype[level] = function () {
            return this.log.apply(this, [level].concat(Array.from(arguments)))
          }
        })
    
    1. Yep, that was me. Crazy small world. Pretty sure there’s a video of us crushing it together somewhere.

Leave a Reply