Top Five features in JavaScript ES6 Worth Mastering
This article is my latest translation on the popular translation
Top 5 JavaScript ES6 features to Learn
Posted: Sept 20th, 2017
JavaScript ES6 adds a number of new language features, some more groundbreaking and widely available than others. Features like ES6 classes, while novel, are really just syntactic sugar on top of existing methods that create classes in JavaScript. Features like generators, while very powerful, are reserved for specific tasks.
From working on various JavaScript related projects over the past 12 months, I’ve found that there are five ES6 features that are indispensable because they really simplify the way common JavaScript tasks are done. Your top 5 May not be the same as mine, and if so, I hope you’ll share them in the comments section at the end.
Let’s get started!
-
Arrow Functions
-
Promises
-
Async Functions
-
Destructuring
-
Default and Rest Parameters
1) JavaScript arrow functions
One of my favorite new features in ES6 JavaScript is not a brand new feature, but a new syntax that makes me smile every time I use it. I’m talking about the arrow function, which provides an extremely elegant and concise way to define anonymous functions.
In short, arrow functions drop the keyword function and use an arrow => to separate the argument part of an anonymous function from the function body:
(x, y) => x * y;Copy the code
This is equivalent to:
function(x, y){
return x * y;
}Copy the code
Or:
(x, y) => {
var factor = 5;
var growth = (x-y) * factor;
}Copy the code
Exactly equivalent to:
function(x, y){
var factor = 5;
var growth = (x-y) * factor;
}Copy the code
The arrow function also eliminates a key source of error when using traditional anonymous functions, namely the value of the this object within the function. With the arrow function, this is lexically-bound, which simply means that its value is bound to the parent scope in a fancy way that never changes. If an arrow function is defined in a custom object, countup, the value of this points to countup without question. Such as:
var countup = {
counter: 15,
start:function(){
window.addEventListener('click', () => {
alert(this.counter) // correctly alerts 15 due to lexical binding of this
})
}
};
countup.start();Copy the code
Where the value of this changes compared to traditional anonymous functions depends on the context in which it is defined. When you try to refer to this.counter in the example above, undefined is returned, which may confuse many who are not familiar with the complexities of dynamic binding. Using the arrow function, the value of this is always predictable and easy to infer.
For a detailed explanation of Arrow Functions, see “Overview of JavaScript Arrow Functions”.
2) JavaScript Promises
JavaScript ES6 Promises Promises make asynchronous task handling linear, a task in most modern Web applications. Rather than relying on callback functions — popularized by JavaScript frameworks such as jQuery. JavaScript Promises uses a central intuitive mechanism to track and respond to asynchronous events. Not only does it make debugging asynchronous code easier, but it also makes writing it a pleasure.
All JavaScript promises start and end with the Promise() constructor:
Const myPromise = new Promise(function(resolve, reject){// call resolve(), reject()})Copy the code
Internally, using the resolve() and Reject () methods, we can signal a Promise object when a Promise is completed or rejected, respectively. The then() and catch() methods can then be called to handle work after a Promise has been fulfilled or rejected.
I use the following variant of the Promise injected with the XMLHttpRequest function to retrieve the external file contents one by one:
function getasync(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open("GET", url)
xhr.onload = () => resolve(xhr.responseText)
xhr.onerror = () => reject(xhr.statusText)
xhr.send()
})
}
getasync('test.txt').then((msg) => {
console.log(msg) // echos contents of text.txt
return getasync('test2.txt')
}).then((msg) => {
console.log(msg) // echos contents of text2.txt
return getasync('test3.txt')
}).then((msg) => {
console.log(msg) // echos contents of text3.txt
})Copy the code
To learn the keys to JavaScript Promises, such as Promise chains and parallel Promise enforcement, read “Beginner’s Guide to Promises”.
3) JavaScript asynchronous functions
In addition to JavaScript promises, asynchronous functions further rewrite the traditional asynchronous code structure to make it more readable. Whenever I show a client code with async programming capabilities, the first reaction is always surprising, followed by curiosity to see how it works.
An asynchronous function consists of two parts:
1) aasync
Is a normal function of the prefix
async function fetchdata(url){
// Do something
// Always returns a promise
}Copy the code
2) In Async function, useawait
The keyword calls the asynchronous operation function
An example is worth a thousand words. Here is the Promise rewritten from the above example to use Async functions instead:
function getasync(url) { // same as original function return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open("GET", url) xhr.onload = () => resolve(xhr.responseText) xhr.onerror = () => reject(xhr.statusText) xhr.send() }) } async function fetchdata(){ // main Async function var text1 = await getasync('test.txt') console.log(text1) var text2 = await getasync('test2.txt') console.log(text2) var text3 = await getasync('test3.txt') console.log(text3) return "Finished" } fetchdata().then((msg) =>{ console.log(msg) // logs "finished" })Copy the code
TXT, test2. TXT, test3. TXT, and finally Finished.
As you can see, in asynchronous functions, we treat the asynchronous function getAsync () as a synchronous function call – there is no then() method or callback to tell us to proceed to the next step. Whenever the keyword await is encountered, execution is paused until getAsync () is resolved, and then goes to the next line in the asynchronous function. The result is the same as using a string of THEN methods based purely on promises.
To learn about asynchronous Functions, including how to await them in parallel, read “Introduction to JavaScript Async Functions- Promises Simplified “.
4) JavaScript deconstruction
Aside from the arrow function, this is the ES6 feature I use the most every day. ES6 destructuring is not a new feature, but a new assignment syntax that lets you quickly unzip values in object properties and arrays and assign them to individual variables.
var profile = {name:'George', age:39, hobby:'Tennis'}
var {name, hobby} = profile // destructure profile object
console.log(name) // "George"
console.log(hobby) // "Tennis"Copy the code
Here I use deconstruction to quickly extract the profile object’s name and Hobby properties.
With aliases, you can use a different variable name than the object property from which you are extracting the value:
var profile = {name:'George', age:39, hobby:'Tennis'}
var {name:n, hobby:h} = profile // destructure profile object
console.log(n) // "George"
console.log(h) // "Tennis"Copy the code
Nested object deconstruction
Deconstruction can also work with nested objects, and I’ve been using it to quickly untangle values from complex JSON requests:
var jsondata = {
title: 'Top 5 JavaScript ES6 Features',
Details: {
date: {
created: '2017/09/19',
modified: '2017/09/20',
},
Category: 'JavaScript',
},
url: '/top-5-es6-features/'
};
var {title, Details: {date: {created, modified}}} = jsondata
console.log(title) // 'Top 5 JavaScript ES6 Features'
console.log(created) // '2017/09/19'
console.log(modified) // '2017/09/20'Copy the code
Deconstruction array
Array destructuring works in much the same way as on objects, except that square brackets are used instead of the left braces:
var soccerteam = ['George', 'Dennis', 'Sandy']
var [a, b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Dennis"Copy the code
You can skip some array elements by using a comma (,) :
var soccerteam = ['George', 'Dennis', 'Sandy']
var [a,,b] = soccerteam // destructure soccerteam array
console.log(a) // "George"
console.log(b) // "Sandy"Copy the code
To me, deconstruction removes all the friction of extracting and assigning object properties and array values in the traditional way. To fully grasp the complexity and potential of ES6 deconstruction, read “Getting to Grips with ES6: Destructuring.”
5) Default and Rest Parameters
Finally, the two ES6 features I most want to bring up are handling function parameters. Almost every function we create in JavaScript accepts user data, so these two features come in handy more than once a month.
Default Parameters
We have all used the following pattern to create parameters with default values:
function getarea(w,h){
var w = w || 10
var h = h || 15
return w * h
}Copy the code
With ES6 support for default parameters, the days of explicitly defined parameter values are over:
function getarea(w=10, h=15){
return w * h
}
getarea(5) // returns 75Copy the code
More details about ES6 default parameters can be found here.
Rest Parameters
Rest Parameters in ES6 make it easy to convert function Parameters into arrays.
function addit(...theNumbers){
// get the sum of the array elements
return theNumbers.reduce((prevnum, curnum) => prevnum + curnum, 0)
}
addit(1,2,3,4) // returns 10Copy the code
By adding three dots before the named parameter… Arguments entered into the function at and after that position are automatically converted to arrays.
Without Rest Parameters, we have to do complicated things like manually converting Parameters to arrays:
function addit(theNumbers){
// force arguments object into array
var numArray = Array.prototype.slice.call(arguments)
return numArray.reduce((prevnum, curnum) => prevnum + curnum, 0)
}
addit(1,2,3,4) // returns 10Copy the code
Rest Parameters can only be applied to a subset of the parameters of a function, such as the following, which only converts the parameters to an array starting with the second:
function f1(date, ...lucknumbers){
return 'The Lucky Numbers for ' + date + ' are: ' + lucknumbers.join(', ')
}
alert( f1('2017/09/29', 3, 32, 43, 52) ) // alerts "The Lucky Numbers for 2017/09/29 are 3,32,43,52"Copy the code
For the complete specification of Rest Parameters in ES6, see here.
conclusion
Do you agree with my top five ES6 features? Which ones do you use the most? Please share them in the comments.