W3docs

JavaScript ES6 Features

A practical guide to JavaScript ES6 (ECMAScript 2015): let and const, arrow functions, template literals, destructuring, classes, modules, promises, and more.

ECMAScript 6 (ES6) is a significant update to the JavaScript language that introduced many new features, making JavaScript more powerful and efficient. This guide provides a detailed exploration of ES6, offering comprehensive explanations and multiple code examples to help you master these new capabilities.

Introduction to ES6

ES6, also known as ECMAScript 2015, brought many improvements and new features to JavaScript. ECMAScript is the official standard that JavaScript implements, and ES6 was its largest revision since 1999. These changes made the language more modern and easier to work with, enhancing both readability and maintainability.

This guide walks through the features you will use most often:

  • Variable declarationslet and const
  • Functions — arrow functions and default parameters
  • Strings — template literals
  • Working with data — destructuring, enhanced object literals, rest/spread
  • Asynchronous code — promises
  • Object-oriented code — classes and modules
  • New collections and primitivesMap, Set, WeakMap, WeakSet, Symbol, iterators, generators, and proxies

Today every modern browser and Node.js supports ES6 natively, so you can use these features without a build step. Each example below is runnable—edit it and press run to experiment.

Let and Const

One of the most notable changes in ES6 is the introduction of let and const for variable declaration. Before ES6, the only option was var, which is function-scoped and is hoisted in a way that often produces surprising bugs. let and const are block-scoped and behave more predictably, which is why modern code rarely uses var at all.

Let

The let keyword allows you to declare variables that are limited in scope to the block, statement, or expression in which they are used.

javascript— editable

In the example above, x declared inside the if block is a separate variable from x declared outside. This demonstrates block-level scoping provided by let. With var, both assignments would refer to the same variable, and the outer console.log would print 20.

let and const are also subject to the temporal dead zone (TDZ): the variable exists from the start of the block but cannot be read or assigned until its declaration runs. Referencing it earlier throws a ReferenceError, which catches typos that var would silently turn into undefined.

Const

The const keyword is used to declare variables whose values are never intended to change. It is block-scoped like let.

javascript— editable

In this example, attempting to reassign a value to y results in an error because const declares a constant whose value cannot be changed.

A common point of confusion: const prevents reassignment of the binding, not mutation of the value. An object or array declared with const can still have its contents changed—you just cannot point the variable at a different object.

javascript— editable
Info

Reach for const by default and only switch to let when you genuinely need to reassign. This prevents accidental changes and signals intent to anyone reading the code.

Arrow Functions

Arrow functions provide a concise syntax for writing function expressions. They also lexically bind the this value, making them particularly useful for writing short functions.

javascript— editable

Here, the arrow function add takes two parameters and returns their sum. When the body is a single expression, you can drop the braces and the return keyword—the expression's value is returned automatically.

The bigger benefit is that arrow functions do not have their own this; they inherit it from the surrounding scope. Before arrow functions, callbacks frequently lost the expected this and developers worked around it with const self = this or .bind(this). Arrow functions make that boilerplate unnecessary:

javascript— editable
Info

Because they have no own this, avoid arrow functions for object methods that rely on this, and for event handlers where you expect this to be the element. Use a regular function in those cases.

Template Literals

Template literals make it easier to create strings, especially when embedding variables or expressions. They use backticks (```) instead of quotes.

javascript— editable

This example shows how template literals allow you to embed the variable name directly into the string, improving readability and convenience. The ${ ... } placeholder can hold any expression, not just a variable—for example `Total: ${price * qty}`. Template literals also span multiple lines without \n, so you can write formatted output or small HTML snippets inline.

Default Parameters

Default parameters allow you to initialize function parameters with default values if no values are provided.

javascript— editable

In this example, the multiply function assigns a default value of 1 to b if no second argument is provided, ensuring the function always returns a valid result.

Destructuring Assignment

Destructuring assignment is a convenient way of extracting values from arrays or objects into distinct variables.

Array Destructuring

javascript— editable

This example shows how array destructuring allows you to assign the values of the numbers array to individual variables a, b, and c.

Object Destructuring

javascript— editable

In this example, object destructuring extracts the name and age properties from the person object into separate variables.

Enhanced Object Literals

ES6 enhances object literals, allowing for a more concise and readable syntax.

javascript— editable

Here, the object obj uses shorthand property names and method definitions, making the object literal more concise.

Promises

Promises provide a way to handle asynchronous operations more efficiently, avoiding callback hell and making the code more readable.

javascript— editable

In this example, a promise is created that resolves after 1 second with the message 'Success!'. The then method is used to handle the resolved value.

Info

Use promises to handle asynchronous operations cleanly and avoid callback hell.

Classes

ES6 introduced classes, providing a clearer and more concise syntax for creating objects and dealing with inheritance.

javascript— editable

This example demonstrates how classes in ES6 offer a clean and intuitive syntax for defining objects and their behavior.

Modules

Modules allow you to break up your code into separate files and import/export functions, objects, or primitives between files.

Exporting

// math.js
export const add = (a, b) => a + b;

Importing

// main.js
import { add } from './math.js';
console.log(add(2, 3)); // 5

In these examples, the add function is exported from math.js and imported into main.js, demonstrating how modules facilitate code organization and reuse.

Rest and Spread Operators

Rest Operator

The rest operator (...) allows you to represent an indefinite number of arguments as an array.

javascript— editable

In this example, the sum function uses the rest operator to gather all arguments into an array, making it easy to perform operations on them.

Spread Operator

The spread operator (...) allows an iterable (like an array) to be expanded in places where zero or more arguments or elements are expected.

javascript— editable

This example shows how the spread operator can be used to combine arrays into a single array, simplifying the code.

Iterators and Generators

Iterators

Iterators are objects that allow you to traverse through a collection, such as an array or string.

javascript— editable

In this example, the iterator provides a way to access each element in the array sequentially.

Generators

Generators are functions that can be paused and resumed, providing a powerful way to handle iterables.

javascript— editable

This example shows how a generator function can yield values one at a time, pausing execution between each yield.

Symbols

Symbols are a new primitive data type introduced in ES6. They are unique and immutable, often used to create unique object keys.

javascript— editable

In this example, symbol1 and symbol2 are unique, even though they have the same description.

Maps and Sets

Maps

Maps are collections of key-value pairs where the keys can be of any type.

javascript— editable

This example demonstrates how to create a map, set key-value pairs, and retrieve values.

Sets

Sets are collections of unique values.

javascript— editable

In this example, the set only contains unique values, even though 3 was added twice.

Proxies

Proxies allow you to create a proxy for another object, enabling you to intercept and redefine fundamental operations.

javascript— editable

This example shows how a proxy can intercept property access, providing a custom response when the property is not found.

WeakMap and WeakSet

WeakMap

WeakMap is similar to Map but only allows objects as keys and does not prevent garbage collection if there are no other references to the key object.

javascript— editable

WeakSet

WeakSet is similar to Set but only allows objects as values and does not prevent garbage collection if there are no other references to the object.

javascript— editable

Conclusion

ES6 brings a wealth of features that make JavaScript a more robust and efficient language. By understanding and utilizing these features, developers can write cleaner, more maintainable code. This guide has provided an in-depth look at the most important aspects of ES6, complete with examples to help you get started.

To go deeper on the individual topics, continue with arrow functions, destructuring assignment, rest parameters and spread syntax, classes, modules, and promises.

Practice

Practice
Which of the following features were introduced in JavaScript ES6?
Which of the following features were introduced in JavaScript ES6?
Was this page helpful?