5 Reasons I Stayed Away from Javascript

And how ES6 is making them right for me again

I am one (of many) who have been trying to avoid using Javascript when ever possible. To me, it is tantamount to an untamed cat which every now and then will jump up into the air in a Pikachu-style attack and dig its claws into my coder’s thigh (I had a cat that did that, and he was cute and cuddly most of the time).

However, the changes ES6 are introducing are hitting the sweet spots so precisely people are already using it in production (Unlike the nasty, awkward Python3 transition where people tried to avoid upgrading. Ugh).

Without further ado, here are the 5 reasons why I stayed away from Javascript, and where ES6 improvements are so welcoming that I’m enjoying now:

#5: Prototype

I mean, seriously? Having to understand a prototype and having to do this

A.prototype = {
printAway: function(val) {
console.log(val);
}
};

hurt me really bad I shut the laptop, went to curl up in the corner and sobbed silently into the night.

“I’m a fine programmer…I’m a fine programmer. It’s not my fault.” I chanted.

With classes in ES6, OOP in Javascript is normal again!

class A {
printAway(val) {
console.log(val);
}
}

#4: Var

This might surprise more than half of Javascript developers out there (this says a lot about how this language is really forgiving many have gone by using it without having to know that much). But using var to create a local variable only works inside a function. Yes, scoping rule in Javascript does not apply to other block statement like if or for loop. So if you have done this before in your code:

var amount = 0;
if (friend) {
var amount = friend.debt;
friend.pay(amount);
}
console.log(amount);   // -> what ever friend.debt is

And your code behaved oddly (or not) at some point, know that what you just did inside the if statement changed the global amount variable.

With ES6’s let keyword, you are to be sure the behavior is as expected:

if (friend) {
  // New local variable is created
let amount = friend.debt;
friend.pay(amount);
}

#3: Broken import

This had really turned me off. No matter how many people said it’s easy using AMD or Common, not having a standard built-in way of managing dependencies was a deal-breaker to me.

With ES6’s import and export statements, this is bound to go away. Stop the require madness already!

export class Animal {
constructor() {
this.sound = undefined;
}
}
export function makeNoise(animal) {
if (animal.sound) {
console.log(animal.sound);
}
}

Importing is very intuitive, aligning to most language’s idiom.

import { Animal, makeNoise } from "./myModules";

#2: Lack of lambdas

The function keyword makes the code harder to read, especially when nested and used as an argument, which is a very common idiom in Javascript.

[1, 2, 3].map(function(x, y) {
return x+y;
});

The function keyword itself is almost as long as the expression, which is quite awkward and not very expressive at all.

The introduction of fat arrows and lambdas in ES6 up Javascript into a rightful functional language.

[1, 2, 3].filter((x, y) => { x > y });

#1: This

I wouldn’t even want to get into this. It is horrendous and an abomination. this keyword is known to be hard to please. It holds an object according to the surrounding context — usually the object invoking the function in which this resides. However, it’s really up to where it is. It can hold a new object in the case of a constructor, undefined in strict mode function calls, and the context object if the function is called as an “object method” as mentioned before.

Then it introduced another abomination in the form of bind, like it’s not crazy confusing enough.

To understand this thoroughly, all you need to know is that Javascript is interpreted, and it does not know what this holds until the function that closes over it is invoked.

function Person() {
// The Person() constructor defines `this` as an
// instance of itself.

this.age = 0;

setInterval(function growUp() {
// In non-strict mode, the growUp() function defines `this`
// as the global object, which is different from the `this`
// defined by the Person() constructor.

this.age++;
}, 1000);
}

var p = new Person();

Since setInterval isn’t called right away by an instance of Person, there’s no way of telling what this is at a construction of a Person.

Again, using the fat arrow, any function created with it can be sure not to create another nonsense closing scope and this can behave more as expected.

function Person() {

this.age = 0;

setInterval(() => {
    // This is really incrementing this Person's age
this.age++;
}, 1000);
}

var p = new Person();

If any of these top your list, hit the ❤ to show you feel `this` and go home and try ES6, or even better, Typescript now.