DEV Community

Victor Zhou
Victor Zhou

Posted on • Originally published at victorzhou.com on

Can You Find The Bug in This Code?

Here’s a bit of Javascript that prints “Hello World!” on two lines:

(function() {
  (function() {
    console.log('Hello')
  })()

  (function() {
    console.log('World!')
  })()
})()

…except it fails with a runtime error. Can you spot the bug without running the code?

Scroll down for a hint.






Hint

Here’s the text of the error:

TypeError: (intermediate value)(...) is not a function

What’s going on?

Scroll down for the solution.






Solution

One character fixes this code:

(function() {
  (function() {
    console.log('Hello')
  })();
  (function() {
    console.log('World!')
  })()
})()

Without that semicolon, the last function is interpreted as an argument to a function call. Here’s a rewrite that demonstrates what’s going on when the code is run without the semicolon:

const f1 = function() { console.log('Hello'); };
const f2 = function() { console.log('World!'); };

f1()(f2)();

There are 3 function invocations in that last line:

  • f1 is called with no arguments
  • The return value of f1() is called with f2 as its only argument
  • The return value of f1()(f2) is called with no arguments

Since the return value of f1() is not a function, the runtime throws a TypeError during the second invocation.

With the semicolon added, this becomes:

const f1 = function() { console.log('Hello'); };
const f2 = function() { console.log('World!'); };

f1();(f2)();

Which runs as expected.

Wait, you had this bug once?

Yup.

Why would you ever write code with so many Immediately Invoked Function Expressions (IIFE)?

It’s a long story - this post explains how I wrote bad enough code to have this bug.

The Lesson

Always use semicolons. This specific case was a bit contrived, but something similar could happen to you. Here’s another Hello World program that fails for a related reason:

const a = 'Hello'
const b = 'World' + '!'
[a, b].forEach(s => console.log(s))

I’ll leave figuring this one out as an exercise for you.

Most Javascript style guides require semicolons, including Google’s, Airbnb’s, and jQuery’s. To summarize: always use semicolons.

Top comments (0)