ES6 (ECMAScript 2015) introduced major improvements to JavaScript. This guide covers all essential ES6 features you need to know.
Let and Const #
let - Block-Scoped Variable #
// var is function-scoped
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
// let is block-scoped
let y = 1;
if (true) {
let y = 2;
console.log(y); // 2
}
console.log(y); // 1
const - Block-Scoped Constant #
const PI = 3.14159;
// PI = 3.14; // Error: Assignment to constant
// Objects can be mutated
const person = { name: "Alice" };
person.name = "Bob"; // OK
person.age = 25; // OK
// person = {}; // Error: Assignment to constant
// Arrays can be mutated
const arr = [1, 2, 3];
arr.push(4); // OK
// arr = []; // Error
Arrow Functions #
// Traditional function
function add(a, b) {
return a + b;
}
// Arrow function
const add = (a, b) => a + b;
// Single parameter
const square = x => x * x;
// No parameters
const greet = () => "Hello";
// Multiple lines
const sum = (a, b) => {
const result = a + b;
return result;
};
// This binding
const obj = {
name: "Alice",
greet: function() {
setTimeout(() => {
console.log(`Hello ${this.name}`); // 'this' from obj
}, 1000);
}
};Template Literals #
const name = "Alice";
const age = 25;
// String interpolation
const greeting = `Hello, ${name}!`;
// Multi-line strings
const message = `
Name: ${name}
Age: ${age}
Next year: ${age + 1}
`;
// Expression evaluation
const price = 10;
const tax = 0.08;
console.log(`Total: $${(price * (1 + tax)).toFixed(2)}`);
// Tagged templates
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<b>${values[i]}</b>` : '');
}, '');
}
const user = "Alice";
const html = highlight`User: ${user}`;Destructuring #
Array Destructuring #
const arr = [1, 2, 3, 4, 5];
// Basic
const [first, second] = arr;
console.log(first, second); // 1 2
// Skip elements
const [a, , c] = arr;
console.log(a, c); // 1 3
// Rest operator
const [head, ...tail] = arr;
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
// Default values
const [x = 0, y = 0] = [1];
console.log(x, y); // 1 0
// Swapping
let a = 1, b = 2;
[a, b] = [b, a];Object Destructuring #
const person = {
name: "Alice",
age: 25,
city: "New York"
};
// Basic
const { name, age } = person;
// Rename variables
const { name: userName, age: userAge } = person;
// Default values
const { name, country = "USA" } = person;
// Nested destructuring
const user = {
id: 1,
profile: {
name: "Alice",
email: "alice@example.com"
}
};
const { profile: { name, email } } = user;
// Function parameters
function greet({ name, age }) {
console.log(`Hello ${name}, age ${age}`);
}
greet(person);Spread and Rest Operators #
Spread Operator (…) #
// Arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Copy array
const copy = [...arr1];
// Objects
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // {a: 1, b: 2, c: 3, d: 4}
// Override properties
const updated = { ...obj1, b: 99 }; // {a: 1, b: 99}
// Function arguments
const numbers = [1, 2, 3];
Math.max(...numbers); // 3
Rest Operator #
// Function parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3, 4); // 10
// With other parameters
function multiply(multiplier, ...numbers) {
return numbers.map(n => n * multiplier);
}
multiply(2, 1, 2, 3); // [2, 4, 6]
Default Parameters #
function greet(name = "Guest", greeting = "Hello") {
return `${greeting}, ${name}!`;
}
greet(); // "Hello, Guest!"
greet("Alice"); // "Hello, Alice!"
greet("Bob", "Hi"); // "Hi, Bob!"
// Expression as default
function createUser(name, id = Date.now()) {
return { name, id };
}
// Previous parameters in defaults
function calculate(x, y = x * 2) {
return x + y;
}Enhanced Object Literals #
const name = "Alice";
const age = 25;
// Shorthand property
const person = { name, age }; // {name: "Alice", age: 25}
// Shorthand methods
const obj = {
greet() {
return "Hello";
},
add(a, b) {
return a + b;
}
};
// Computed property names
const key = "dynamicKey";
const obj2 = {
[key]: "value",
[`${key}2`]: "value2"
};Classes #
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
static create(name, age) {
return new Person(name, age);
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
return `${this.name} is studying`;
}
}
const student = new Student("Alice", 20, "A");Modules #
Export #
// Named exports
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export class Calculator {
multiply(a, b) {
return a * b;
}
}
// Export list
const a = 1;
const b = 2;
export { a, b };
// Export with rename
export { a as valueA, b as valueB };
// Default export
export default function() {
console.log("Default export");
}Import #
// Named imports
import { PI, add } from './math.js';
// Import with rename
import { PI as pi } from './math.js';
// Import all
import * as math from './math.js';
math.add(1, 2);
// Default import
import myFunction from './module.js';
// Mixed
import defaultExport, { namedExport } from './module.js';Promises #
// Create promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success");
}, 1000);
});
// Consume promise
promise
.then(result => console.log(result))
.catch(error => console.error(error));
// Promise.all
Promise.all([promise1, promise2, promise3])
.then(results => console.log(results));
// Promise.race
Promise.race([promise1, promise2])
.then(result => console.log(result));Iterators and Generators #
Iterators #
const iterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step <= 3) {
return { value: step, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const value of iterable) {
console.log(value); // 1, 2, 3
}Generators #
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// Infinite generator
function* infiniteNumbers() {
let i = 0;
while (true) {
yield i++;
}
}
// Generator with parameters
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (const num of range(1, 5)) {
console.log(num); // 1, 2, 3, 4, 5
}Map and Set #
Map #
const map = new Map();
// Set values
map.set('name', 'Alice');
map.set('age', 25);
map.set(1, 'number key');
// Get values
console.log(map.get('name')); // "Alice"
// Check existence
console.log(map.has('age')); // true
// Size
console.log(map.size); // 3
// Iterate
for (const [key, value] of map) {
console.log(key, value);
}
// Delete
map.delete('age');
// Clear
map.clear();Set #
const set = new Set();
// Add values
set.add(1);
set.add(2);
set.add(2); // Duplicate ignored
// Check existence
console.log(set.has(1)); // true
// Size
console.log(set.size); // 2
// Iterate
for (const value of set) {
console.log(value);
}
// Array to Set (remove duplicates)
const arr = [1, 2, 2, 3, 3, 4];
const uniqueArr = [...new Set(arr)]; // [1, 2, 3, 4]
Symbol #
// Create symbols
const sym1 = Symbol();
const sym2 = Symbol('description');
// Symbols are unique
console.log(Symbol() === Symbol()); // false
// As object keys
const obj = {
[Symbol('key')]: 'value'
};
// Well-known symbols
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
For…of Loop #
// Arrays
const arr = [1, 2, 3];
for (const num of arr) {
console.log(num);
}
// Strings
const str = "hello";
for (const char of str) {
console.log(char);
}
// Maps
const map = new Map([['a', 1], ['b', 2]]);
for (const [key, value] of map) {
console.log(key, value);
}
// Sets
const set = new Set([1, 2, 3]);
for (const value of set) {
console.log(value);
}ES6 modernized JavaScript significantly. These features make code more concise, readable, and maintainable. Use them to write better JavaScript.