My Favourite ES6 Features
Posted on 13th March 2017
ECMAScript 6 (ES6 for short) is ancient now by internet standards, but that is all the more reason to use it. Why? Because many browsers (and of course, Nodejs) now natively support it. For those who are unfamiliar with ES6, it's an extension to the JavaScript standard that provides many useful features that make it all the more pleasant to use. Of course, not enough older browsers support many of its features, so you will still need to use a transpiler such as Babel if you plan on writing ES6 in production. But is ES6 worth the hassle? It sure is. Here are my favourite features.
let and const
Javascript's var
leaves much to be desired. While const
and let
are not the most glamorous features, they serve a very useful purpose. Let's begin with let
.
if (2 > 1) {
var x = 42;
}
console.log(x); // 42
JavaScript is a bit different from many programming languages in that variables are function scoped (that is, they are accessible throughout a function, but not outside of it, unless if they are global). Many other languages, such as the C family, use block scoped variables - blocks such as if, while, for etc. isolate local variables. let
brings this familiar scoping to JavaScript.
if (2 > 1) {
let x = 42;
}
console.log(x); // ReferenceError: x is not defined
const
functions very similarily to let
in that it is block scoped, but it also brings some, well, stability to variables. Variables declared by a const
cannot be changed later. However, there is an important distinction: while the variable itself is a constant (immutable), but the value might still be possible to be changed. If you use const for types such as integers, you will generally be fine, but a const
object can still have its values changed.
Arrow functions
Due to JavaScript's nature of using callbacks, you will eventually end up writing code that (ab)uses anonymous functions. Take this for example:
const my_array = [2, 3, 4];
const result = my_array.map(function (x) {
return x * 3;
});
Not very pleasant, huh? The problem becomes far worse when you have multiple callbacks and many arguments.
const my_array = [2, 3, 4];
const result = my_array.map(x => x * 3);
Simple callbacks can be made far less verbose. If you use a simple expression, it is returned automatically so you do not even need a return
. If you have one parameter, you can omit the parentheses (zero argument arrow functions still require parentheses - one argument is the special case). For more complicated code, you'll want to wrap the anonymous function with a braces that make it a block.
const my_array = [2, 3, 4];
const result = my_array.map((x) => {
let final_result = x;
final_result *= 3;
final_result += 2;
return final_result;
});
The arrow functions also provide lexical scoping of this
which you can read about here.
Class syntax sugar
This is one of the most controversial ES6 features because it could mislead some programmers into misunderstanding how JavaScript works. I, however, welcome the change, as it makes classes look like classes rather than funky functions. In "classical" (ES5 etc.) JavaScript, to make a "class" you would do something like:
function Employee(name, age) {
this.name = name;
this.age = age;
}
Employee.prototype.introduce = function() {
return "Hello! My name is " + this.name + " and I am " + this.age + ".";
}
first_employee = new Employee("John Smith", 42);
console.log(first_employee.introduce());
A function that becomes a class when you use new
is a bit strange in my opinion. The prototype
is not much better. Luckily, ES6 introduces nicer-looking syntax that does the same thing in the background:
class Employee {
constructor(name, age) {
this.name = name;
this.age = age;
}
introduce() {
return "Hello! My name is " + this.name + " and I am " + this.age + ".";
}
}
first_employee = new Employee("John Smith", 42);
console.log(first_employee.introduce());
Truly a breath of fresh air. If you need to declare methods outside of the class, you can, using the old prototype
syntax too - the class
syntax is just syntactic sugar! But that string looks pretty ugly, but luckily, ES6 has the solution!
Template literals
Let's return to our introduce
method:
Employee.prototype.introduce = function() {
return "Hello! My name is " + this.name + " and I am " + this.age + ".";
}
Doing tasks like this is very common in JavaScript as you usually want to display some variables in the DOM eventually. ES6 makes variable interpolation in strings muhc more human-friendly:
Employee.prototype.introduce = function() {
return `Hello! My name is ${this.name} and I am ${this.age}.`;
}
The backticks also allow you to write text spanning multiple lines with nothing more than newlines. Simple, but very certainly useful.
Default parameter values
While many languages enjoyed such a feature for years, in JavaScript programmers were forced to endure something like this if they wanted default values for function parameters:
function compute(x, y, z) {
if (y === undefined) {
y = 3;
}
if (z === undefined) {
z = 10;
}
return (x + y) * z;
}
ES6 removes the need for such annoying "header" code:
function compute(x, y = 3, z = 10) {
return (x + y) * z;
}
Surely everyone agrees that this is a superior solution.
Conclusion
What I covered here barely scratches the surface, but it should give a nice taste to those who are still unaware of ES6's features. For further reading, I recommend the far more indepth Exploring ES6 book which the author made available for free on the website.