ES2016
JavaScript keeps evolving. There is a specification for JavaScript (aka. ECMAScript), but not all browsers/engines adopt it with the speed. This means it isn't possible to use every new JavaScript feature in every environment.
There is a tool called Babel, which transpiles newer versions of JavaScript to "old" JavaScript. The good thing about this compared to other compilers that where mentioned earlier is, that it's still plain JavaScript. You could also use the pre-compilers mentioned earlier, to get access to a bigger feature-set, but there are a two downsides with that:
Less resources available
When it comes to writing an application it's very common to look up problems that might occur during development. The community of a pre-compiler like TypeScript is way smaller compared to the one of JavaScript. Less people using it means also less resources available, which can slow down the development.
Less future-proof
If the company behind a pre-compiler decides to stop maintaining the project, developers are left with what's already there. Web technologies are moving fast, and if something can't keep up with whats considered state of the art it's likely to be abandoned soon. Applications should be future-proof, so why not choose technologies which are meant to stay.
That's why more and more developers are settling down with the latest JavaScript has to offer.
Why ES2016?
Why should someone even consider ES2016, if they have to transpile it anyway? There are a hand-full of features which make working with a newer version of JavaScript so much better*. These include constants, arrow functions, classes and modules. And since ES2016 is going to be default in every browser soon, transpilation will be obsolete soon. In the meanwhile it's well worth the hassle to transpile the code to get access to the latest and greatest JavaScript has to offer.
A feature which really makes a difference in code quality is async/await. It prevents something called callback hell.
Callback hell
Due to the asynchronous nature of JavaScript it's common to use callbacks if something isn't synchronous. For example a timeout. Here is what a callback looks like:
function waitOneMinute(callback) {
setTimeout(callback, 1000 * 60)
}
waitOneMinute(() => {
console.log('One minute is over!')
})
This doesn't look to bad. But what if there is a chain of asynchronous function calls?
waitOneMinute(() => {
console.log('One minute is over!')
waitOneMinute(() => {
console.log('Two minutes are over!')
waitOneMinute(() => {
console.log('Three minutes are over!')
waitOneMinute(() => {
console.log('Four minutes are over!')
})
})
})
})
It can get messy very quickly! Even if this particular example isn't very likely to happen in the real world, there are enough cases where this could happen. For example if there are multiple web requests which depend on each other.
The solution
Here is what the same example looks like with async/await.
async function waitOneMinute() {
return new Promise(resolve, reject) {
setTimeout(resolve, 1000 * 60)
}
}
await waitOneMinute()
console.log('One minute is over!')
await waitOneMinute()
console.log('Two minutes are over!')
await waitOneMinute()
console.log('Three minutes are over!')
await waitOneMinute()
console.log('Four minutes are over')
This way, the code stays clean, no matter how many asynchronous calls are chained together.