Instantly share code, notes, and snippets.

Embed
What would you like to do?

When a beginner asks you "when do I use semi-colons?" would you rather say this?

// what people who say "use semicolons!!" say
class Foo {
  prop = {
  }; // yes

  static bar () {
    if (stuff) {
      doStuff(); // yes
    } // no

    for (var key in obj) {
    } // no

    return {
    }; // yes
  } // no

  foo () {
  } // no
} // no

Foo.prop = {
}; // yes

things.map(thing => thing.name /*no*/)

var boing = function () {
}; // yes

function boing () {
} // no

/*no*/[1,2,3].map(); // yes
/*no*/(function () {})(); // yes

Or this?

// what people who say "don't use semicolons!" say
/*yes*/;[1,2,3].map()
/*yes*/;(function () {})()
// which are two things I haven't done in the last 3 years, mind you

In the end, I'd rather not talk about semi-colons, and just do what people around me want me to do, but when teaching a beginner who asks (and they ALWAYS ask this) "when do I use a semi-colon", I just put my face in my hands and say "I don't have any answers for you".

@jaketrent

This comment has been minimized.

Copy link

jaketrent commented May 4, 2015

Hearty +1 :) lol

@steida

This comment has been minimized.

Copy link

steida commented May 4, 2015

Brilliant. I have the same problem once I switched back to ES6 from CoffeeScript. Personally, I tell my students something like "You don't have to write them. There are only two cases you never run over anyway, especially with eslint which you are using already. But for public projects, you have to use semi-colons, because some people have obsession or fetish about them, and it always ends in endless bikeshedding." I have just one simple rule for semi-colon: Don't ask, don't tell.

@goatslacker

This comment has been minimized.

Copy link

goatslacker commented May 4, 2015

There are some really edge cases where a missing semicolon will break things.

  • Regarding template literals in ES6, which only applies if the template literal is preceded by an identifier:

    const world = 'world'
    foo
    `hello${world}`
    
    // parsed as foo`hello${world}` which is a [tagged template](http://odetocode.com/blogs/scott/archive/2014/09/30/features-of-es6-part-8-tagged-templates.aspx)

    This is riddled with Things You Shouldn't Do™ like:

    • Have a line that ends with an identifier.
    • Start a line with a string.
  • Also, arithmetic operators:

    1
    +2
    // parsed as 1 + 2

Which again, are things you would never want to do in the first place. In practice, semicolons are easier to omit than they are to include.

I wrote more about this subject here. The tl;dr is don't treat JS as if it had significant newlines but rather we should strive to understand ASI, and understanding ASI is easier to grok when you think about when you should add semicolons rather than when you should omit them.

@ALF-er

This comment has been minimized.

Copy link

ALF-er commented May 5, 2015

Just say: "Put semicolon after expressions and don't after statements".

@murashki

This comment has been minimized.

Copy link

murashki commented May 5, 2015

It would be great to have syntax like this:

/*
  No semi-colons
*/
var a = 1

/*
  New line means new expression
*/
var b = a + 2
a = 3

/*
  Some operators at the end of line may indicate that
  line is broken. In this case we should use indent.
*/
var b = a +
  2 * 6

var c = 2 +
  3 +
  5

/*
  Some operators may indicate that line was broken if they
  starts a line.
*/
var b = a
  .someMethod("yo!")

/*
  Expressions may share one line using comma
*/
var a = 1, console.log(a)

/*
  Define object and arrays without comma
*/
var obj = {
  "abc": "ABC"
  "xyx": "XYZ"
}

var arr = [
  12
  34
]

/*
  Bu we can still define array in one line style. We
  need comma to achive this (as with expressions)
*/
var arr = [12, 43]

var arr = [
  12, 43
  45
]

/*
  Function parameters
*/
someFunction(1, 2, 3, 4)

someFunction(
  1, 2
  3
  4
)

/*
  Constructions may not use braces but must use indents
*/
function abc()
  var a = 1
  return a + 1

for (var key in obj)
  console.log(key)

/*
  But when we use construction as a parameter or
  assing it to a variable, we need braces
*/
var abc = function () {
  var a = 1
}

someFunction(function () {
  a * 2
}, "value")

/*
  Only anonymous functions may not use return
*/
// Returns "abc" without `return` keyword
var a = function () {
  "abc"
}
// But in this case `return` is required
function a()
  return "abc"

/*
  All operators needs spaces around
*/
var a = 1 + 2 * 3
if ( ! a)
  console.log("!a");

/*
  But . must go without spaces around
*/
var a = b.c.x() + m.l()

/*
  Insert expression in strings using \{}, not ${}
*/
console.log("My name is \{name}");

/*
  Use {} as property ref
*/
var a = {
  "abc": "ABC"
  "f": function () {
    "xyz"
  }
}
console.log(a.{"abc"})
console.log(a.{"f"}())

If also would be great use func instead of function.

What do you think about this? ))

@nmn

This comment has been minimized.

Copy link

nmn commented May 9, 2015

I would add one extra rule: Never write a return statement without a value following it. So ban this:

return

and always write one of.

return undefined
return null
return 0
return someValue

This is an improvement over the always write semi-colons approach.

When you always write semi-colons, it makes you think this would work correctly:

return
  {a: 1}

However, if you don't write unnecessary semi-colons, you're already used to treating lines as statements, and are much less likely to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment