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!

  1. Arrow Functions

  2. Promises

  3. Async Functions

  4. Destructuring

  5. 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) aasyncIs a normal function of the prefix

async function fetchdata(url){
	// Do something
	// Always returns a promise
}Copy the code

2) In Async function, useawaitThe 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.