Fabien Huet

Fabien
Huet

Web ninja //
CTO on demand

Home Github About me

šŸšØ ES6 and ESNext new features are not drop-in replacements for ES5 deprecated features

in TypeScript, JavaScript

I see more and more articles telling us that we should drop our old function or var keywords to switch to the new and better () => {}, const and let. These features have many advantages and you should use them. But not as drop-in replacements.

The fat arrow function () => {}

The fat arrow function () => {} is not equivalent to function() {}. It is not just syntactic sugar to ease your eyes. You will break your applications with unexpected bugs if you simply replace one by the other. Mostly because the fat arrow function does not create a new context. It means that this is the same inside and outside of the brackets : when the old function keyword creates a new context.

Here is what is gives in action:

const myObject = {
    func: function() { console.log(this) },
    arrowFunc: () => { console.log(this) },
};

myObject.func();
// {func: ʒ, arrowFunc: ʒ}

myObject.arrowFunc();
// Window {parent: Window, opener: null...
// or any global object if you are not executing in the broswer

Sometimes you want a new context, sometimes you donā€˜t. It depends on your use case. But if you have a sufficiently complex application, there are roughly 100% chances that it is at some point relying on the fact that a function is creating a new context. So donā€™t blindly ā€œupdateā€ to the new syntax.

var let const

It is easy to understand that you cannot replace var by const everywhere. A const should never be reassigned and you can see in your code that you reassign sometimes.

But I have read a few times that let is a perfect drop-in replacement for var. It is not.

let is not hoisted

Here is the ā€œnot hoistedā€ in action:

console.log(foo);
// Uncaught ReferenceError: foo is not defined
let foo = 'bar';

console.log(foo);
// undefined
var foo = 'bar';

When declaring a variable with var, the declaration is hoisted at the top of the scope (but not the assignation, this is why it logs undefined and not bar). When declaring a variable with let, it is not. So if you search/replace var by let in a project, it is almost certainly breaking something.

let is block scoped.

Here is the ā€œblock scopedā€ in action:

for(let i = 0; i < 1; i++) {}
console.log(i)
//  Uncaught ReferenceError: i is not defined

for(var i = 0; i < 1; i++) {}
console.log(i)
// 1

The let has been defined in a block and is not accessible outside of that block. It can even be a simple bracket block as { let i = 1; }. Once again, if you blindly replace all your vars by lets, you will break things.

But by all means, do it. The way let behaves is usually better than the way var behaves. Break your app and fix it to work with let.

Conclusion

The old ES5 keywords are not deprecated. They do things that ES6 features cannot do. So we should keep them and use them when needed.

ES6 allow cleaner code and will force you to block scope for example. This is a good thing.