Contents
Introduction
Younger I was a dogmatic developer blindly enforcing the IT gurus’ dogma, later I’ve become more pragmatic preferring code readability and maintainability.
In JavaScript, it means omitting the semicolons to lighten the code and remove useless ceremony.
But in some rare corner cases omitting a semicolon can completely change the way the compiler interprets the code.
Hopefully, it will cause a compilation error, and in the worst case a hidden bug hard to track.
In this article, I describe one of these corner cases.
A simple code
Here is a basic JavaScript code snippet whose meaning is quite obvious for a human developer:
var evens = [], odds = [] var n = 123 console.log("n is %s", n % 2 === 0 ? 'even' : 'odd') (n % 2 === 0 ? evens : odds).push(n)
If n
is even it is added to the evens
array, otherwise to the odds
array.
A strange error
But compiling it raise a TypeError
:
(n % 2 === 0 ? evens : odds).push(n)
^
TypeError: console.log(…) is not a function
at Object. (C:\Temp\test.js:7:1)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
The error is telling that we cannot call the return value of console.log
as it is not a function!
Apparently, the compiler has misunderstood our intent.
What the compiler sees
Indeed here is how the compiler interprets the last lines:
console.log("n is %s", n % 2 === 0 ? 'even' : 'odd')(n % 2 === 0 ? evens : odds).push(n)
Not the same meaning at all, here the call to the return value of console.log
is obvious.
Clarifying our intent
To help the compiler understand that we have two separate instructions we must separate them with a semicolon:
console.log("n is %s", n % 2 === 0 ? 'even' : 'odd'); (n % 2 === 0 ? evens : odds).push(n)
Now the code runs as expected pushing n
to the relevant array.
Conclusion
Even after years of practice JavaScript can still surprise you with subtle errors you would not get in other languages.
Let’s say this is what makes it somehow flavorful. 😉