3

I'm wondering if this is a compiler bug, or this is the way it's supposed to be.

Using node.js v10.15.3, this code throws an error:

var x
x = false
(function y() { console.log('foo') }())

But this code works fine:

var x
x = false;
(function y() { console.log('foo') }())

It's the semicolon that makes the difference. The error message is: "TypeError: false is not a function", so it appears that without the semicolon, the compiler is parsing the open paren after the "false" keyword as a function call, as if I had written "x = false()". It took me a long time to figure out what was going wrong in my code (which was more complex than the example above, obviously.) That's a chunk of my life I won't get back!

My question is: why? I thought semicolons were not necessary at the end of a line? I've just been reading the ECMA spec on semicolon insertion trying to figure this out, but it's still a little murky to me.

I guess the moral of the story is to just go ahead and terminate all lines with semicolons. The funny thing is that, as a C programmer, that was my habit, and I was just trying to catch up with the times by dropping all those unneeded semicolons.

Duncan
  • 507
  • 3
  • 14
  • Check the rules of *automatic semicolon insertion* (ASI) : https://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi – Christian C. Salvadó May 18 '19 at 04:48

3 Answers3

3

JavaScript parser see this

var x
x = false
(function y() { console.log('foo') }())

as this:

var x;
x = false(function y() { console.log('foo') }());

which means you're trying to call false as a function. This is because JS parser always tries to get the longest expression.

In most cases, to write JS with or without semicolons is just a matter of styling. However, you'll need to add semicolons when:

  • There are 2 lines of code, and
  • the first line ends with a possible identifier (or keywords, like if or while), and
  • The second line starts with a bracket.

In this case the semicolon should be added to the end of the first line, or the beginning of the second line.

R Xy
  • 197
  • 6
1

You're right about false being called as a function. Your first code block is equivalent to this:

var x
x = false(function y() { console.log('foo') }())

As there is no semicolon separating the lines, the js interpreter calls the keyword false, passing in the function y as an argument. This obviously results in an error as false is not callable.

Semicolon use is almost required in this case, where an open parenthesis is the furs character on a line. A way use semicolons only when necessary is to place them before an open parenthesis, like follows:

var x
x = false
;(function y(){...})
jro
  • 900
  • 1
  • 10
  • 21
0

In some cases line breaks doesn't matter. In the cases where the code would be right syntax without line break.

Consider the below snippet where a nested function is called with two () and calling is separated by one line. But it doesn't matter.

function x(){
  return function(){ return 6}
}
let a =
x()

()
console.log(a) //6

The above line will still be evaluated as

let a = x()()

The general rule is that where ever the code makes sense and doesn't throw error without a semicolon. It doesn't insert semi color there. It only inserts semicolon when there is no other choice.

Maheer Ali
  • 35,834
  • 5
  • 42
  • 73