We've all been following the progress of the JavaScript language, from its humble beginnings (ECMAStript 3, in 1999) to the version that is part of the HTML5 standard (ECMAScript 5, 2011), to the latest and greatest version (ECMAScript 6, aka Harmony, ES2015, ES6 Harmony) that everyone is talking about. (For more details, see https://en.wikipedia.org/wiki/ECMAScript.)
With each new release, there are tons of improvements and additions to the language. Some of these improvements are probably very relevant to your work, and could make your life easier and improve the quality of the code you write.
Unfortunately, not all are available today on all browsers, so you may have to use polyfills or tools like TypeScript or Babel if you want your apps to run in IE11 (which still has about 12% marketshare).
In our company, we have been using TypeScript for a long time, which allowed us to use essential new features such as classes and modules while still targeting ECMAScript 5 so our apps run in IE 9.
In this blog, I want to mention two ES6 features not as well-known as classes and modules, but extremely useful and usable today: arrow functions and the let keyword.
Arrow Functions
Arrow functions consist of replacing the traditional “function(parameters) {}” function expression syntax with the more succinct “() => {}” syntax. They have two main advantages:
- Shorter syntax, and
- Lexical binding for the "this" value.
The second advantage is the more interesting one. Consider these two code snippets:
// old style
this.start();
var self = this;
setTimeout(function() {
self.stop();
}, 100);
The “self” variable is needed to keep a reference to the current context, because “this” within the function body means something else (not very well-defined). Now check out the same thing written using an arrow function:
// new style
this.start();
setTimeout(() => {
this.stop();
}, 100);
This is shorter, and the “this” variable retains its lexical meaning as most people would expect. The result is shorter and clearer code. Enough with those “self” and “that” variables already!
Arrow functions were added to ES6 and have become one of its most popular new features. They are not supported in IE11 and earlier, but if you use TypeScript you can and should start using them today.
You can read more about arrow functions in the Mozilla Developer Network:
https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Functions
The “let” keyword
I never thought there was anything wrong with the “var” keyword. I used it all the time, and rarely ran into any issues. You know, things like:
var t = startTime;
this.on(‘tick’, () => {
... code that uses t ...
if (this.altitude() <= 0) {
var t = doSomething();
...
}
});
Of course, the “t” variable declared in the function body is the same as the one declared at the top of the block. Until recently, I was happy to call this a bug, blame the developer (myself) and change the name of the inner variable.
But, there are some other issues with “var” that are less common and a lot harder to track down and fix. For example:
var messages = 'Hello,JavaScript,World'.split(',');
for (var i = 0; i < messages.length; i++) {
setTimeout(function() {
alert(messages[i]);
})
}
This doesn’t work as most people would expect. It is not a bug, it is a consequence of how the “var” keyword works. Namely, there’s a single variable here, and it runs through the entire for loop before executing the first “timeOut”.
At this point you could do some research and find a solution, which will typically look like this:
for (var i = 0; i < messages.length; i++) {
(function(index) {
setTimeout(function() {
alert(messages[index]);
});
})(i);
}
Which does work, but is nearly impossible to read (for me at least).
Oh, well... just another JavaScript quirk we have to live with, right?
Not really. I recently read an excellent article in the ES6 In Depth series: let and const. Basically, it explains that the “var” keyword has implementation quirks that could not be fixed without breaking existing code, so “let” was added to replace it. You can use it to fix the example above like this:
let messages = 'Hello,JavaScript,World'.split(',');
for (let i = 0; i < messages.length; i++) {
setTimeout(() => {
alert(messages[i]);
})
}
If you simply replace all instances of “var” with “let” in your code, chances are it will run exactly as before. If you're working on a large project and using TypeScript, chances are you'll find a couple of bugs as well, like variables being re-declared as we mentioned above.
After reading the article, I switched to “let”. Now the TypeScript compiler can check more of my code and help prevent more subtle bugs before they happen.
The “let” keyword is supported by IE11 and better. If you are using TypeScript and targeting ES3, it will generate “vars” for you so your app will run in IE9 as well.