Object structures and functions are possibly two of the most commonly utilized syntactic features in JavaScript, as they both have important roles in defining classes in object-oriented programming. In ES6, defining methods and functions has become much easier with the help of concise properties and methods, and especially arrow functions, which may help to limit the lines of code you have to write.
In the previous installment of this series, we took a closer look at the spread operator, default parameters, and destructuring assignment, all important features of ES6 that are useful within functions.
But what about writing the functions themselves? In this third installment, we’ll delve into syntactic particularities of ES6, including those that affect our code on a large scale, such as arrow functions and concise properties, and on a smaller scale, like string interpolation, computed property names, and for
… of
loops.
Concise properties and methods
In ES5, defining a property sharing the same name as its identifier was a repetitive affair. In ES6, to define a property having the same name as a lexical identifier, you can use concise properties.
// ES5 var obj = { foo: function() { // ... }, bar: function() { // ... } };
// ES6 const obj = { foo() { // ... }, bar() { // ... } };
Computed property names
With computed property names, it’s possible to write an expression that is computed during property name assignment, such that you can have dynamically named properties based on other inputs.
var suffix = "Computed"; var obj = { foo() { // ... }, [ "bar" + suffix ]() { // ... }, [ "baz" + suffix ]() { // ... } };
String interpolation
With template literals now present in ES6, you can employ string interpolation by surrounding the entire string with backticks. This also means you can spread them across multiple lines, thus obviating the need for \n
(carriage returns) within strings.
var name = "Dries"; var hello = `Greetings to you, my dear friend ${name}.`;
You can also place expressions and other interpolated strings within an interpolated string.
var name = "Dries"; var hello = `Greetings to you, my dear friend ${name.toUpperCase()}.`;
Arrow functions
Arrow functions are perhaps the most distinctive new syntactic feature in ES6, even for those unversed in JavaScript. Functions can now be declared more concisely without the function
keyword. Arrow functions look the same as functions written in the traditional way; the only cosmetic difference is that they abbreviate traditional function syntax. In practice, however, arrow functions don’t receive an arguments
object that is callable within the function, as traditional functions do. There is another crucial difference, which I approach shortly.
var foo = a => { console.log(a * 3) }; var bar = (b, c) => { console.log(b + c) };
If there is no surrounding function block indicated by curly braces, then a return
statement is assumed.
var foo = a => a * 3; var bar = (b, c) => b + c;
In ES5, when this
is used inside a method’s function, as seen below, it refers to the surrounding method — the owner of the function — thus permitting access to all of the method’s properties. However, when a subroutine is defined within the method’s function (such as the anonymous function below), this instead refers to the window
or global
object, which is the actual owner of the subroutine. This necessitates another variable like self
to be defined ...
// Inside an object definition: name: "Dries Buytaert", // ES5 greet: function (people) { var self = this; people.forEach(function (person) { console.log(self.name + ' greets ' + person); }); },
… or an invocation of bind()
to provide the surrounding this
.
// ES5 greet: function (people) { people.forEach(function (person) { console.log(this.name + ' greets ' + person); }.bind(this)); },
In ES6, the value of this
is lexical, meaning that it is not shadowed from its surroundings. In other words, the value of this
is equivalent to the surrounding method, not the window
or global
object.
// ES6 greet(people) { people.forEach(person => console.log(this.name + ' greets ' + person)); },
Interestingly enough, arrow functions are mostly syntactic sugar for the bind()
example above.
for
… of
loops
One of the most interesting new syntactic features in ES6 is for
… of
loops, which iterate over array values, not simply keys (indexes). In the ES6 example below, the value that is being presented in the console is the array member’s value, not its index — as would be the case in a for
… in
loop.
var arr = [1, 2, 3, 4, 5]; for (var index in arr) { console.log(index); // 0 1 2 3 4 }
// ES5 for (var index in arr) { console.log(arr[index]); // 1 2 3 4 5 }
// ES6 for (var value of arr) { console.log(value); // 1 2 3 4 5 }
It’s important to note here that for
loops with both the in
and of
keywords are discouraged in the Airbnb ES6 standards currently under review for adoption by the Drupal community. This section is intended to help you if you encounter it in the wild, but it should not be used when contributing to Drupal core and following Drupal’s coding standards (if the Airbnb standards are indeed adopted).
Conclusion
Some of the most distinctive features of ES6 upend the way we write JavaScript. One-line function expressions via arrow functions, for instance, evoke possibilities when it comes to efficiency. But it’s essential to remember that using such techniques can detrimentally impact code legibility. As with every syntactic feature, we have an obligation to future developers who handle our code to consider each use of these features in the context of maintainability.
In this installment of the “Introduction to ES6” blog series, we inspected some of the new syntactic features available in ES6, including concise properties, computed property names, arrow functions, and string interpolation. In the fourth and final installment, we’ll zoom out even further, moving from functions to object-oriented programming and entire files with ES6 classes and modules. Finally, we’ll end with one of the most important concepts in ES6: promises.
New to this series? Check out the first part and second part of the "ES6 for Drupal developers" blog series. This blog series is a heavily updated and improved version of “Introduction to ES6”, a session delivered at SANDCamp 2016. Special thanks to Matt Grill for providing feedback during the writing process.