this, that, and everything else


JavaScript / Saturday, November 24th, 2018

One of the most puzzling things in JavaScript is this.

We could begin by explaining what it is, what it does, and what makes it complicated, but this is not a tutorial. This is a rant, and like all good rants, it should begin with an example. ūüôā

Let’s write some code for an object that is able to introduce itself after, say, a second has elapsed:

 
 
obj = {
      name: 'Object',
  introduce: function(){
        return setTimeout(function(){ console.log(this.name); }, 1000);
  }
};
obj.introduce();

Now, let’s run this code in JSFiddle:

And we get the expected . . . result????

What? Why? How?

Hmm, maybe JSFiddle has some sorcery going on that messes with my code. No fear, we shall persevere and try this code in a new tab console of Chrome:

And now we get . . . 18??? What the fuck is going on? Are the computing gods trolling me?

Well, if you understand what’s going on here, congratulations, you’re an excellent JS developer and should close this window now. On the other hand, if you’re pulling your hair,¬†you don’t know JS¬†and need to level up asap.

Regardless, one thing needs to be established forever: this is fundamental to JavaScript (at least in the browser) and attempts to hide it will only lead to chaos.

Which brings me to one of my biggest complaints with ES6: classes.

You can define a class in ES6 like this:

 
 
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

But more importantly, what does a class represent in JavaScript? Absolutely nothing!

The JavaScript API has no concept (I repeat, no concept) of classes. There are no base classes, derived classes, and so on. And yet, in ES6 we can do stuff like this (code examples copied shamelessly from MDN):

 
 
class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}
class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }
  speak() {
    console.log(this.name + ' barks.');
  }
}
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

Behind the scenes, the new JavaScript engine is converting all this to plain-old objects, functions and prototypal inheritance. You can work it out when you’re experienced with JavaScript, but for a new developer, ES6 simply builds more walls around the ugly garden of core JavaScript. How it benefits anyone I’m unable to understand.

It’s fine if you’re writing server-side JavaScript, I fear the day when this syntax will be part of browsers, where this¬†gets really complicated really fast (as we saw at the start of this post). Will a new trick will then be introduced to hide the fact that classes hide objects and contexts underneath?

The very thought makes me shudder!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.