Skip to main content

Modern JavaScript (ES6+)

JavaScript has evolved rapidly since ES6 (2015). Each year brings new features that make the language more expressive and developer-friendly. This chapter covers the essential modern features you should know.

1. Destructuring

Extract values from arrays and objects into distinct variables.

Array Destructuring

const colors = ['red', 'green', 'blue'];

// Basic
const [first, second, third] = colors;
// first = 'red', second = 'green', third = 'blue'

// Skip elements
const [, , lastColor] = colors; // 'blue'

// Rest operator
const [primary, ...others] = colors;
// primary = 'red', others = ['green', 'blue']

// Default values
const [a, b, c, d = 'yellow'] = colors;
// d = 'yellow' (default since colors[3] is undefined)

// Swap variables
let x = 1, y = 2;
[x, y] = [y, x]; // x = 2, y = 1

Object Destructuring

const person = { name: 'Alice', age: 25, city: 'NYC' };

// Basic
const { name, age } = person;

// Rename
const { name: personName, age: personAge } = person;

// Default values
const { name, country = 'USA' } = person;

// Nested
const user = {
    id: 1,
    profile: { firstName: 'Alice', lastName: 'Smith' }
};
const { profile: { firstName } } = user; // 'Alice'

// Rest
const { name, ...rest } = person;
// rest = { age: 25, city: 'NYC' }

Function Parameters

// Destructure in parameters
function greet({ name, age }) {
    return `Hello ${name}, you are ${age}`;
}

greet({ name: 'Alice', age: 25 });

// With defaults
function createUser({ name = 'Guest', role = 'user' } = {}) {
    return { name, role };
}

createUser(); // { name: 'Guest', role: 'user' }

2. Spread Operator

Expand iterables (arrays, strings) or objects.

Arrays

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// Combine arrays
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// Copy array (shallow)
const copy = [...arr1];

// Convert iterable to array
const chars = [...'hello']; // ['h', 'e', 'l', 'l', 'o']

// Pass as function arguments
Math.max(...arr1); // 3

Objects (ES2018)

const defaults = { theme: 'dark', lang: 'en' };
const userPrefs = { theme: 'light' };

// Merge (later properties win)
const settings = { ...defaults, ...userPrefs };
// { theme: 'light', lang: 'en' }

// Copy object (shallow)
const copy = { ...defaults };

// Add/override properties
const updated = { ...defaults, debug: true };

3. Template Literals

Enhanced string formatting with backticks.
const name = 'Alice';
const age = 25;

// Interpolation
const greeting = `Hello, ${name}!`;

// Expressions
const message = `You will be ${age + 10} in 10 years`;

// Multi-line strings
const html = `
    <div class="card">
        <h1>${name}</h1>
        <p>Age: ${age}</p>
    </div>
`;

// Tagged templates (advanced)
function highlight(strings, ...values) {
    return strings.reduce((result, str, i) => {
        const value = values[i] ? `<mark>${values[i]}</mark>` : '';
        return result + str + value;
    }, '');
}

const highlighted = highlight`Hello ${name}, you are ${age}`;
// 'Hello <mark>Alice</mark>, you are <mark>25</mark>'

4. Modules (ES6)

Organize code into reusable files.

Named Exports

// utils.js
export const PI = 3.14159;

export function add(a, b) {
    return a + b;
}

export class Calculator {
    // ...
}

// main.js
import { PI, add, Calculator } from './utils.js';
import { add as sum } from './utils.js'; // Rename
import * as utils from './utils.js';     // Import all

Default Exports

// User.js
export default class User {
    constructor(name) {
        this.name = name;
    }
}

// main.js
import User from './User.js';              // Any name works
import MyUser from './User.js';            // Same thing
import User, { helper } from './User.js'; // Default + named

Dynamic Imports

Load modules on demand (code splitting).
// Lazy load a module
const button = document.getElementById('load');

button.addEventListener('click', async () => {
    const { heavyFunction } = await import('./heavy-module.js');
    heavyFunction();
});

5. Classes (ES6+)

Syntactic sugar over prototypes with additional features.
class Animal {
    // Private field (ES2022)
    #heartRate = 60;
    
    // Static field
    static kingdom = 'Animalia';
    
    constructor(name) {
        this.name = name;
    }
    
    // Getter
    get info() {
        return `${this.name} (${Animal.kingdom})`;
    }
    
    // Method
    speak() {
        console.log(`${this.name} makes a sound`);
    }
    
    // Private method (ES2022)
    #checkVitals() {
        return this.#heartRate > 0;
    }
    
    // Static method
    static create(name) {
        return new Animal(name);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }
    
    speak() {
        console.log(`${this.name} barks!`);
    }
}

6. New Data Structures

Map (Key-Value, Any Type Keys)

const map = new Map();

// Any type as key
map.set('name', 'Alice');
map.set(1, 'one');
map.set({ id: 1 }, 'object key');

map.get('name');  // 'Alice'
map.has(1);       // true
map.size;         // 3
map.delete('name');

// Iteration
for (const [key, value] of map) {
    console.log(key, value);
}

Set (Unique Values)

const set = new Set([1, 2, 2, 3, 3, 3]);
// Set(3) {1, 2, 3}

set.add(4);
set.has(2);    // true
set.delete(1);
set.size;      // 3

// Remove duplicates from array
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]

WeakMap & WeakSet

Keys are weakly held (garbage collected if no other references).
const weakMap = new WeakMap();
let obj = { data: 'secret' };

weakMap.set(obj, 'metadata');
weakMap.get(obj); // 'metadata'

obj = null; // obj can be garbage collected, entry removed

7. New Array & Object Methods

Array Methods (ES2019+)

// flat: Flatten nested arrays
[[1, 2], [3, [4, 5]]].flat(2); // [1, 2, 3, 4, 5]

// flatMap: map + flat(1)
[1, 2].flatMap(x => [x, x * 2]); // [1, 2, 2, 4]

// at: Negative indexing
const arr = [1, 2, 3, 4, 5];
arr.at(-1);  // 5 (last element)
arr.at(-2);  // 4

// findLast / findLastIndex (ES2023)
arr.findLast(x => x % 2 === 0);      // 4
arr.findLastIndex(x => x % 2 === 0); // 3

// toSorted, toReversed, toSpliced (ES2023) — Non-mutating
const sorted = arr.toSorted((a, b) => b - a); // [5, 4, 3, 2, 1]
const reversed = arr.toReversed();             // [5, 4, 3, 2, 1]
// Original arr unchanged!

Object Methods (ES2017+)

const obj = { a: 1, b: 2, c: 3 };

// Object.entries / fromEntries
Object.entries(obj);              // [['a', 1], ['b', 2], ['c', 3]]
Object.fromEntries([['x', 10]]); // { x: 10 }

// Transform object
const doubled = Object.fromEntries(
    Object.entries(obj).map(([k, v]) => [k, v * 2])
);
// { a: 2, b: 4, c: 6 }

// Object.hasOwn (ES2022) — Safer than hasOwnProperty
Object.hasOwn(obj, 'a'); // true

8. Other Modern Features

Optional Chaining & Nullish Coalescing

const user = { profile: { name: 'Alice' } };

// Optional chaining
user?.profile?.name;      // 'Alice'
user?.address?.city;      // undefined (no error)
user?.getName?.();        // undefined (function doesn't exist)

// Nullish coalescing
const value = null ?? 'default';  // 'default'
const zero = 0 ?? 'default';      // 0 (0 is not nullish)

Logical Assignment (ES2021)

let a = null;
let b = 'hello';

a ??= 'default'; // a = 'default' (was null)
b ??= 'default'; // b = 'hello' (unchanged)

let x = 0;
x ||= 10;        // x = 10 (0 is falsy)
x &&= 20;        // x = 20 (x was truthy)

Numeric Separators (ES2021)

const billion = 1_000_000_000;
const bytes = 0xFF_FF_FF_FF;
const binary = 0b1010_0001;

String Methods (ES2017+)

// Padding
'5'.padStart(3, '0');  // '005'
'5'.padEnd(3, '0');    // '500'

// Trim
'  hello  '.trim();      // 'hello'
'  hello  '.trimStart(); // 'hello  '
'  hello  '.trimEnd();   // '  hello'

// replaceAll (ES2021)
'aabbcc'.replaceAll('a', 'x'); // 'xxbbcc'

// at (ES2022)
'hello'.at(-1); // 'o'

Summary

Modern JavaScript is expressive, concise, and powerful:
  • Destructuring: Extract values from objects/arrays elegantly.
  • Spread/Rest: Combine, copy, and collect elements.
  • Modules: Organize code with import/export.
  • Classes: Clean OOP syntax with private fields.
  • Map/Set: Powerful data structures beyond objects/arrays.
  • Optional Chaining: Safe property access with ?..
Next, we’ll learn about DOM & Browser APIs, how JavaScript interacts with web pages.