WTF JavaScript: A Variable with Side Effects

Lars Grammel - Jan 16 '22 - - Dev Community

JavaScript has many quirks and difficult-to-understand behaviors. There are hilarious talks such as WTFJS and WAT that make fun of JavaScript for its strangeness.

Since I work on refactorings, I have to consider many weird and sometimes funny sides of JavaScript. I will share some of the surprising behaviors that I encounter, so if you see them (which you hopefully never will), it might hint at what's going on.

This blog post explores an innocent-looking statement:

// ... some code

helloWorld;
Enter fullscreen mode Exit fullscreen mode

You might intuitively think that nothing should happen here - the statement seems to do nothing because there is no obvious function call here.

However, it can do anything, for example, print "Hello World!" to the console.

// ... some code

helloWorld;           // prints "Hello World!"
Enter fullscreen mode Exit fullscreen mode

How can this even be possible?

It turns out that global variables (in this case, helloWorld) are properties of the global object. And properties in JavaScript do not have to be simple values. They can be implemented using getters and setters, which can execute code. Since the global object inherits from Object.prototype in modern JavaScript engines, adding properties to Object.prototype creates properties on the global object.

Here, helloWorld is defined as such a getter:

Object.defineProperty(Object.prototype, 'helloWorld', {
  get() { console.log("Hello World!"); },
});

helloWorld;           // prints "Hello World!"
Enter fullscreen mode Exit fullscreen mode

Thankfully this can only happen with global variables, and not with parameters or local variables.

Object.defineProperty(Object.prototype, 'helloWorld', {
  get() { console.log("Hello World!"); },
});

const a = helloWorld; // getter is evaluated, prints "Hello World!"
a;                    // does nothing
Enter fullscreen mode Exit fullscreen mode

I learned about this strange behavior in a blog post about the globalThis polyfill. In the polyfill, a global property getter is used to access the global this object in different environments such as browsers, web workers, frames, Node.js, and ES modules. Have a look if you want to know more!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .