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
- Arrow Functions
- A new
this
scope - Promises
- Generators
let
andconst
- Classes
- Modules
- Template Literals
- Default parameters
- The spread operator
- Destructuring assignments
- Enhanced Object Literals
- For-of loop
- Map and Set
- New String methods
- New Object methods
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:
const something = () => {
//...
}
Arrow functions also provide a shorter syntax for one-liner functions and functions with a single parameter:
const something = () => doSomething()
const something = param => doSomething(param)
While arrow functions offer a new way to define functions, regular function
s 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 function
s, 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:
// 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:
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.
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.
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.
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.
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.
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:
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:
const c = [...a]
The spread operator works similarly with objects and strings:
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:
const person = {
firstName: 'Tom',
lastName: 'Cruise',
actor: true,
age: 54,
}
const {firstName: name, age} = person
You can also extract specific elements from an array:
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:
const something = 'y'
const x = {
something
}
Prototype
You can specify a prototype for an object:
const anObject = { y: 'y' }
const x = {
__proto__: anObject
}
super()
You can use the super()
keyword to refer to the parent object:
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:
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.
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:'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.