/

The ES6 Guide: Everything You Need to Know about ECMAScript 2015

The ES6 Guide: Everything You Need to Know about ECMAScript 2015

ECMAScript, often abbreviated as ES, is the standard that JavaScript is based on. ES6, also known as ES2015, introduced many new features and enhancements to the language. In this guide, we will explore the most important additions made in ES6.

Table of Contents

Introduction

ECMAScript 2015, also known as ES6, is a major version of the ECMAScript standard. It was published 4 years after the previous revision, ECMAScript 5.1, and marked the switch from using edition numbers to year numbers in the naming of the standard. ES6 introduced many new features and changes, making it an important update for JavaScript developers.

Arrow Functions

Arrow functions are a concise and visually appealing way to define functions in JavaScript. They have changed the way JavaScript code looks and works. For example, a traditional function can be written as an arrow function like this:

1
2
3
const something = () => {
//...
}

Arrow functions also provide a shorter syntax for one-liner functions and functions with a single parameter:

1
2
3
const something = () => doSomething()

const something = param => doSomething(param)

While arrow functions offer a new way to define functions, regular functions will continue to work as they did before.

A new this scope

One of the benefits of arrow functions is that they automatically inherit the this scope from their surrounding context. With regular functions, the value of this is determined by how the function is called, sometimes leading to confusion and the need for workarounds like var that = this. Arrow functions solve this problem by eliminating the need to explicitly bind this.

Promises

Promises are a powerful feature that helps eliminate the problem of “callback hell” in asynchronous JavaScript code. ES2015 standardized the concept of promises, which were already being used in JavaScript through various libraries. Promises provide a more structured way of dealing with asynchronous operations by allowing you to chain multiple operations together.

Here’s an example that demonstrates the difference between using a callback and using a promise:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Using callbacks
setTimeout(function() {
console.log('I promised to run after 1s')
setTimeout(function() {
console.log('I promised to run after 2s')
}, 1000)
}, 1000)

// Using promises
const wait = () => new Promise((resolve, reject) => {
setTimeout(resolve, 1000)
})

wait().then(() => {
console.log('I promised to run after 1s')
return wait()
})
.then(() => console.log('I promised to run after 2s'))

Promises provide a cleaner and more structured way of organizing and handling asynchronous code.

Generators

Generators are a special type of function that can pause and resume their execution. This feature allows other code to run while the generator is paused. Generators are particularly useful when dealing with asynchronous operations, as they provide a more readable and straightforward way to write asynchronous code.

For a detailed explanation of generators, refer to JavaScript Generators Guide.

let and const

In ES6, two new variable declarations, let and const, were introduced. Unlike the traditional var declaration, which has function scope, let and const have block scope. This means that variables declared with let or const are limited to the block where they are defined, such as inside a loop or an if statement.

Additionally, const variables are immutable, meaning their value cannot be changed once assigned. This makes const a popular choice for variables that should not be reassigned.

The use of var is now less common, and let and const are preferred for variable declarations in modern JavaScript code.

Classes

ES6 introduced the concept of classes to JavaScript, bringing object-oriented programming features familiar to developers from other languages. Classes provide a more familiar and structured way to define and inherit objects.

Here’s an example of using classes in JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person {
constructor(name) {
this.name = name
}

hello() {
return 'Hello, I am ' + this.name + '.'
}
}

class Actor extends Person {
hello() {
return super.hello() + ' I am an actor.'
}
}

var tomCruise = new Actor('Tom Cruise')
tomCruise.hello()

In this example, we define a Person class with a constructor and a hello method. We then define an Actor class that extends the Person class and overrides the hello method to add additional information.

Classes in JavaScript provide a more structured and familiar way to define objects and implement inheritance.

Constructor

Classes have a special method called constructor that is called when a class is initialized using the new keyword. This method is used to set initial values for the class properties.

Super

The super keyword allows you to refer to the parent class within a subclass. It is often used to call the parent class’s constructor or methods.

Getters and setters

ES6 introduced getter and setter methods for class properties. Getters are used to retrieve the value of a property, while setters are used to set the value of a property. This provides a more controlled way to access and modify class properties.

Modules

Before ES6, JavaScript had multiple competing standards for modules, leading to fragmentation within the community. ES2015 standardized the module system, providing a unified and consistent way to manage dependencies in JavaScript projects.

Importing modules

In ES6, modules can be imported using the import ... from ... syntax. This makes it easy to include functions, objects, or classes defined in other modules within your code.

1
2
3
4
import * as mymodule from 'mymodule'
import React from 'react'
import { React, Component } from 'react'
import React as MyLibrary from 'react'

Exporting modules

ES6 also introduced the export keyword, which allows you to export functions, objects, or classes from a module so that they can be used by other modules.

1
2
export var number = 2
export function bar() { /* ... */ }

Modules provide a standardized and modular approach to managing code dependencies in JavaScript projects.

Template Literals

Template literals are a new syntax for creating strings in JavaScript. They provide a more flexible and expressive way to define strings compared to traditional string concatenation.

1
const aString = `A string`

Template literals allow you to embed expressions within strings using the ${expression} syntax. This makes it easy to insert values or perform complex expressions within strings.

1
2
3
4
5
6
7
8
9
10
11
const joe = 'test'
const string = `something ${joe}` //something test

const string = `something ${1 + 2 + 3}`
const string2 = `something ${doSomething() ? 'x' : 'y' }`

const string3 = `Hey
this

string
is awesome!`

Template literals also support multiline strings, eliminating the need for manual line breaks or concatenation.

For a more in-depth guide on template literals, refer to this post.

Default parameters

ES6 introduced support for default values in function parameters. This allows you to specify default values that will be used if no value is provided for the parameter.

1
2
const someFunction = function(index = 0, testing = true) { /* ... */ }
someFunction()

Default parameters make it easier to handle cases where a function expects some optional parameters without the need for additional checks or conditions.

The spread operator

The spread operator (...) allows you to expand arrays, objects, or strings into individual elements. It provides a concise way to combine or copy elements from one variable to another.

For example, you can use the spread operator to create a new array by combining multiple arrays:

1
2
const a = [1, 2, 3]
const b = [...a, 4, 5, 6]

You can also use the spread operator to create a copy of an array:

1
const c = [...a]

The spread operator works similarly with objects and strings:

1
2
3
4
const newObj = { ...oldObj }

const hey = 'hey'
const arrayized = [...hey] // ['h', 'e', 'y']

The spread operator can also be used to pass an array as arguments to a function.

Destructuring assignments

Destructuring assignments allow you to extract values from arrays or objects and assign them to variables in a single statement. This provides a more concise and readable way to access and use specific values from complex data structures.

For example, given an object, you can extract specific properties and assign them to variables:

1
2
3
4
5
6
7
8
const person = {
firstName: 'Tom',
lastName: 'Cruise',
actor: true,
age: 54,
}

const {firstName: name, age} = person

You can also extract specific elements from an array:

1
2
const a = [1, 2, 3, 4, 5]
const [first, second] = a

Destructuring assignments provide a more convenient way to work with complex data structures.

Enhanced Object Literals

ES2015 introduced enhancements to object literals, providing additional flexibility and functionality when creating objects.

Simpler syntax to include variables

Instead of explicitly stating the property and value, you can use a shorter syntax with object literals:

1
2
3
4
const something = 'y'
const x = {
something
}

Prototype

You can specify a prototype for an object:

1
2
3
4
const anObject = { y: 'y' }
const x = {
__proto__: anObject
}

super()

You can use the super() keyword to refer to the parent object:

1
2
3
4
5
6
7
8
const anObject = { y: 'y', test: () => 'zoo' }
const x = {
__proto__: anObject,
test() {
return super.test() + 'x'
}
}
x.test() //zoox

Dynamic properties

You can use dynamic properties in object literals:

1
2
3
4
const x = {
['a' + '_' + 'b']: 'z'
}
x.a_b //z

Enhanced object literals offer more flexibility and options for creating and defining objects.

For-of loop

The for-of loop was introduced in ES6 as a more concise and readable way to iterate over collection-like objects, such as arrays or strings. It combines the simplicity of the forEach loop with the ability to break out of the loop.

1
2
3
4
5
6
7
for (const v of ['a', 'b', 'c']) {
console.log(v);
}

for (const [i, v] of ['a', 'b', 'c'].entries()) {
console.log(i, v);
}

The for-of loop makes it easier to iterate over and work with collections in JavaScript.

Map and Set

ES6 introduced two new built-in data structures, Map and Set, which provide more flexible and efficient ways to store and retrieve data.

For a detailed explanation of Map and Set, refer to JavaScript Data Structures: Map and JavaScript Data Structures: Set.

New String methods

ES6 introduced new instance methods for string values, providing more functionality and options when working with strings.

Two notable examples are:

  • repeat() repeats a string a specified number of times:

    1
    'Ho'.repeat(3) //HoHoHo
  • codePointAt() retrieves the Unicode code of characters that require more than one UTF-16 unit.

These new methods make it easier and more efficient to work with strings in JavaScript.

New Object methods

ES6 added several static methods under the Object namespace, providing additional functionality for working with objects.

Some notable additions are:

  • Object.is() determines if two values are the same value.
  • Object.assign() is used to shallow copy properties from one object to another.
  • Object.setPrototypeOf() sets the prototype of an object.

These new methods offer more flexibility and options for working with objects.

Tags: ECMAScript, ES6, JavaScript, Arrow Functions, this scope, Promises, Generators, let and const, Classes, Constructor, Super, Getters and setters, Modules, Importing modules, Exporting modules, Template Literals, Default parameters, The spread operator, Destructuring assignments, Enhanced Object Literals, Prototype, super(), Dynamic properties, For-of loop, Map and Set, New String methods, New Object methods.