ECMAScript 6 - 10 Awesome New Features
Did you know that JavaScript (along with JScript and ActionScript) is an implementation of a general purpose client-side scripting language specification called ECMAScript? To make this nasty definition a little bit more attractive, we can say that ECMAScript (or officially ECMA-262) is the standard that defines how we use JavaScript, and what we can accomplish with it.
The latest, 6th edition of the language, ECMAScript 2015 (or ES6) is probably the most significant update since the first version in 1997. The main goal of the latest release has been to provide a better support for creating larger applications and libraries. This means a more mature syntax, new shortcuts to make coding easier, and also new methods, keywords, data types, and many other enhancements.
ES6 documentation is extensive, if you like to read a lot, you can download the whole specs from the website of ECMA International. In this post we will take a look at 10 handpicked features, even though ES6 has much more to offer. If you want to experiment with it, ES6 Fiddle is a great place to do so, and you can also find some sample code snippets there.
Support for ECMAScript 6
Browser vendors have been gradually adding support for the features of ECMAScript 6. You can find a cool compatibility table here about the browser and compiler support for the new features.
If you are interested in ES6 support in Node.js, check out the docs here.
Although not all features are currently supported, we can use transpilers such as Babel to transpile our ES6 code to ES5. There is a cool Grunt plugin for Babel, many awesome ES6 plugins for Grunt, and an amazing Gulp-Babel plugin out there, so luckily we have plenty of choices.
This way we can start to use the enhanced syntax and capabilities, while we don’t have to worry about compability issues. Now let’s see the features.
1. New let
Keyword
ES6 introduces the new let
keyword that allows us to declare local variables in the scope of a block, such as a statement, an expression, or a(n inner) function. For example we can declare a for
loop in the following way, then reuse the same variable name (as its scope is limited to the for
loop) inside the next if
statement:
1 2 3 4 5 6 7 8 9 10 11 | for (let i = 0; i < myArray.length; i++) { // Do something inside the block } if (x > 0 && x != y) { // We reuse "i" let i = x * y } |
Using the let
keyword leads to a cleaner and more usable code. The difference between let
and var
is in the scope, for example a local variable defined by the var
keyword can be used in the entire enclosing function, while variables defined by let
only work in their own (sub)block. Let
can also be used globally, in this case it behaves the same way as var
. Of course, in ES6 we can still use var
if we want.
2. New const
Keyword
The new const keyword makes it possible to declare constants, also known as immutable variables, to which we cannot reassign new content later.
1 2 3 4 5 6 | const MY_CONST = 12; console.log(MY_CONST); // 12 MY_CONST = 16; // Silent error, as we cannot reassign a new value to a constant |
Immutable variables are not always fully immutable in ECMAScript 6 though, as if a constant holds an object, we can later change the value of its properties and methods. The same is true for the elements of an array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | const MY_CONSTANT = {myProperty: 6}; console.log(MY_CONSTANT.myProperty); // 6 MY_CONSTANT.myProperty = 18; console.log(MY_CONSTANT.myProperty); // 18 const OTHER_CONSTANT = [12, 14, 16]; console.log(OTHER_CONSTANT[0]); // 12 OTHER_CONSTANT[0] = 22; console.log(OTHER_CONSTANT[0]); // 22 |
We still can’t directly reassign a new value to the MY_CONSTANT object in the above code snippet, which means we cannot change the names of the properties and methods, an also cannot add a new or delete an existing one, so we cannot do the following thing:
1 2 3 | MY_CONSTANT = {newProperty: 18}; console.log(MY_CONSTANT.newProperty); // error |
3. Arrow functions
ECMAScript 6 facilitates how we write anonymous functions, as we can completely omit the function
keyword. We only need to use the new syntax for arrow functions, named after the => arrow sign (fat arrow), that provides us with a great shortcut.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // 1. One parameter in ES6 let sum = (a, b) => a + b; // in ES5 var sum = function (a, b) { return a + b; }; // 2. Without parameters in ES6 let randomNum = () => Math.random(); // in ES5 var randomNum = function () { return Math.random(); }; // 3. Without return in ES6 let message = (name) => alert( "Hi " + name + "!" ); // in ES5 var message = function (yourName) { alert( "Hi " + yourName + "!" ); }; |
There’s an important difference between regular and arrow functions, that is arrow functions don’t receive a this
value automatically like functions defined with the function
keyword do. Arrow functions lexically bind the this
value to the current scope. This means that we can easily reuse the this
keyword in an inner function. In ES5 it is only possible with the following hack:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // ES5 Hack to use the "this" keyword in an inner function { ... addAll: function addAll(pieces) { var self = this ; _.each(pieces, function (piece) { self.add(piece); }); }, ... } // ES6 the same inner function now can use its own "this" { ... addAll: function addAll(pieces) { _.each(pieces, piece => this .add(piece)); }, ... } |
Code above is from Mozilla Hacks
4. New spread
Operator
The new spread
operator is marked with 3 dots (…), and we can use it to sign the place of multiple expected items. One of the most common use cases of the spread operator is inserting the elements of an array into another array:
1 2 3 4 5 6 | let myArray = [1, 2, 3]; let newArray = [...myArray, 4, 5, 6]; console.log(newArray); // 1, 2, 3, 4, 5, 6 |
We can also take leverage of the spread
operator in function calls in which we want to pass in arguments from an array:
1 2 3 4 5 6 7 8 | let myArray = [1, 2, 3]; function sum(a, b, c) { return a + b + c; } console.log(sum(...myArray)); // 6 |
The spread
operator is quite flexible, as it can be used multiple times in the same array or function call.
5. Default Values for Parameters & New Rest Parameters
Good news, that in ECMAScript 6 we can add default values to the parameters of a function. This means that if we don’t pass in arguments later in the function call, the default parameters will be used. In ES5 the default values of parameters are always set to undefined
, so the new possibility to set them to whatever we want is definitely a great enhancement of the language.
1 2 3 4 5 6 7 8 9 | function sum(a = 2, b = 4) { return a + b; } console.log( sum() ); // 6 console.log( sum(3, 6) ); // 9 |
ES6 also introduces a new kind of parameter, the rest parameters. They look and work similarly to spread operators. They come handy if we don’t know how many arguments will be passed in later in the function call. We can use the properties and methods of the Array object on rest parameters:
1 2 3 4 5 6 7 8 9 | function putInAlphabet(...args) { let sorted = args.sort(); return sorted; } console.log( putInAlphabet( "e" , "c" , "m" , "a" , "s" , "c" , "r" , "i" , "p" , "t" ) ); // a,c,c,e,i,m,p,r,s,t |
6. New for...of
Statement
With the help of the new for...of
loop we can iterate over arrays or other iterable objects easily. Along with the new for...of
statement, ECMAScript 6 introduces two new iterable objects too, Map for key/value maps, and Set for collections of unique values that can also be primitive values and object references. When we use the for...of
statement, the code inside the block is executed for each element of the iterable object.
1 2 3 4 5 6 7 8 9 | let myArray = [1, 2, 3, 4, 5]; let sum = 0; for (let i of myArray) { sum += i; } console.log(sum); // 15 (= 1 + 2 + 3 + 4 + 5) |
7. Template Literals
ECMAScript 6 provides us with a new alternative for string concatenation. Template literals allow us to easily create templates in which we can embed different values to any spot we want. To do so we need to use the ${...}
syntax everywhere where we want to insert the data that we can pass in from variables, arrays, or objects in the following way:
1 2 3 4 5 6 7 | let customer = { title: 'Ms' , firstname: 'Jane' , surname: 'Doe' , age: '34' }; let template = `Dear ${customer.title} ${customer.firstname} ${customer.surname}! Happy ${customer.age}th birthday!`; console.log(template); // Dear Ms Jane Doe! Happy 34th birthday! |
8. Classes
ES6 introduces JavaScript classes that are built upon the existing prototype-based inheritance. The new syntax makes it more straightforward to create objects, take leverage of inheritance, and reuse code. It will also make it easier for beginners arriving from other programming languages to understand how JavaScript works.
In ES6 classes are declared with the new class
keyword, and need to have a constructor()
method that is called when a new object is instantiated by using the new myClass()
syntax. It’s also possible to extend new classes with the class Child extends Parent
syntax that can be familiar from other object-oriented languages such as PHP. It’s also important to know that, unlike function and variable declarations, class declarations are NOT hoisted in ECMAScript 6.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Polygon { constructor(height, width) { //class constructor this .name = 'Polygon' ; this .height = height; this .width = width; } sayName() { //class method console.log( 'Hi, I am a' , this .name + '.' ); } } let myPolygon = new Polygon(5, 6); console.log(myPolygon.sayName()); // Hi, I am a Polygon. |
Code above from ES6 Fiddle Examples, .
9. Modules
Have you ever wondered about how cool it would be if JavaScript was modular? Of course, there have been workarounds such as CommonJS (used in Node.js) or AMD (Asynchronous Module Definition) (used in RequireJS) to do that before, but ES6 introduces modules as a native feature.
We need to define each module in its own file, then use the export
keyword to export variables and functions to other files, and the import
keyword to import them from other files, according to the following syntax:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // functions.js function cube(a) { return a * a * a; } function cubeRoot(a) { return Math.cbrt(a); } export { cube, cubeRoot} // or: export { cube as cb, cubeRoot as cr } // app.js import { cube, cubeRoot } from 'functions' ; console.log(cube(4)); // 64 console.log(cubeRoot(125)); // 5 |
This solution is brilliant, as the code stored in a module is invisible from outside, and we need to export only the part that we want to get accessed by other files. We can do much more amazing things with ES6 Modules, here you can find a great and detailed explanation about them.
10. Loads of New Methods
ECMAScript 6 introduces many new methods for the existing String Prototype, Array Object, Array Prototype, and Math Object. The new methods can significantly improve the way how we can manipulate these entities. Mozilla Dev has great code examples of the new additions, it’s worth to take time and thoroughly examine them.
Just to show how cool they really are, here is my favourite: the find method of the Array prototype, that enables us testing a certain criteria on the elements of an array by executing the callback function on each element, then returning the first element that returns true
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function isPrime(element, index, array) { var start = 2; while (start <= Math.sqrt(element)) { if (element % start++ < 1) { return false ; } } return element > 1; } console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found console.log([4, 5, 8, 12].find(isPrime)); // 5 |
Code above from: Mozilla Dev