JavaScript: ES6+ Modern Features

Master the modern JavaScript syntax that makes code shorter, clearer, and more expressive.

Array Destructuring

Array destructuring unpacks values from an array into individual variables by position, removing the need for manual index access.

Array Destructuring

Variables on the left are matched to array positions on the right in order.

  • Skip elements with a comma: const [, second] = arr
  • Provide a default: const [a = 0] = [], used when the element is undefined
  • Swap variables cleanly: [a, b] = [b, a]
  • Works on any iterable: arrays, strings, Sets, Maps

Array Destructuring

Unpack by position, skip slots, set defaults, and swap variables in one line.

Object Destructuring

Object destructuring extracts properties by name into local variables. You can rename them and provide defaults in the same expression.

Object Destructuring

Properties are matched by key name, order does not matter.

  • Rename while destructuring: const { name: userName } = user
  • Default value: const { role = "guest" } = user
  • Combine rename and default: const { role: r = "guest" } = user
  • Most common use: destructuring function parameters to pull out needed fields

Object Destructuring

Extract, rename, and set defaults all in one destructuring expression.

Nested Destructuring

You can destructure nested objects and arrays by mirroring the structure on the left-hand side.

Nested Destructuring

Mirror the shape of the data on the left side to reach deeply nested values in one step.

  • Each level of nesting adds another layer of braces or brackets on the left
  • Apply defaults at any depth
  • Keep it readable, if it gets complex, pull out intermediate variables instead

Nested Destructuring

Reach deep into an object or array in a single destructuring expression.

Rest in Destructuring

The rest syntax (...) inside a destructuring pattern collects everything that was not explicitly extracted.

Rest in Destructuring

Use rest to extract a few properties and group the remainder into a new variable.

  • Must be the last item in the destructuring pattern
  • In arrays: collects remaining elements into a new array
  • In objects: collects remaining properties into a new object
  • Common use: separating props you need from the rest you will forward

Rest in Destructuring

Pull out what you need and collect the remainder with ...

Spread Operator

The spread operator (...) expands an iterable or object into individual elements. It is the opposite of rest.

Spread Operator

Spread copies elements or properties out, use it to clone, merge, or pass arrays as arguments.

  • Arrays: clone, concatenate, or insert elements without mutating the original
  • Objects: shallow-clone or merge objects, later keys overwrite earlier ones
  • Function calls: spread an array into individual positional arguments
  • Spread creates a shallow copy, nested objects are still referenced, not deep-cloned

Spread in Arrays, Objects, and Function Calls

Expand iterables and objects to clone, merge, or pass as arguments.

Rest Parameters

Rest parameters collect all remaining function arguments into a real array, replacing the old arguments object.

Rest Parameters

Rest parameters give variadic functions a clean, array-based way to handle any number of arguments.

  • Syntax: function fn(first, ...rest)
  • Must be the last parameter
  • Unlike arguments, rest is a true Array, use map, filter, reduce on it directly
  • Arrow functions do not have arguments, rest parameters are the only option

Rest Parameters

Collect extra arguments into a real array, no more arguments object.

Template Literals

Template literals use backticks (`) instead of quotes and support embedded expressions with ${} and multi-line strings without escape characters.

Template Literals

Template literals replace string concatenation with readable inline expressions.

  • Embed any expression: variables, ternaries, function calls
  • Multi-line strings without \n, just press Enter inside the backticks
  • Tagged templates let a function process the template (used by styled-components, GraphQL)
  • Nesting template literals is allowed for complex expressions

Template Literals

Embed expressions and write multi-line strings without concatenation or escape characters.

Arrow Functions

Arrow functions provide a shorter syntax for writing functions and inheritthis from the surrounding scope instead of creating their own.

Arrow Functions

Arrow functions are ideal for short callbacks, they are concise and never rebind this.

  • Single expression: implicit return, no braces needed: x => x * 2
  • Multiple statements: need braces and an explicit return
  • No own this, arguments, or super
  • Cannot be used as constructors (new ArrowFn() throws)

Arrow Functions

Shorter syntax with implicit returns for single expressions, perfect for callbacks.

Default Parameters

Default parameters assign a fallback value to a function parameter when the caller passesundefined or nothing at all.

Default Parameters

Default parameters eliminate the if (!arg) arg = default pattern inside function bodies.

  • Triggered when the argument is undefined, passing null does NOT trigger the default
  • Default can be any expression, including a function call
  • Later parameters can reference earlier ones: function fn(a, b = a * 2)
  • Combine with destructuring defaults for flexible config objects

Default Parameters

Set safe fallbacks directly in the signature, no manual checks needed inside the body.

Enhanced Object Literals

ES6 added three shorthand features for defining object literals: property shorthand, method shorthand, and computed property names.

Enhanced Object Literals

Less repetition and more expressive object definitions.

  • Property shorthand: { name } instead of { name: name }
  • Method shorthand: { greet() {} } instead of { greet: function() {} }
  • Computed keys: { [varName]: value }, the key is evaluated at runtime

Enhanced Object Literals

Shorthand properties, shorthand methods, and computed keys in one example.

for...of Loop

for...of iterates over the values of any iterable (arrays, strings, Sets, Maps, generators), in contrast tofor...in which iterates over keys.

for...of

Use for...of when you need the values, use for...in only when you specifically need the keys.

  • Works on all iterables: Array, String, Set, Map, NodeList, generator
  • Pair with entries() to get both index and value: for (const [i, v] of arr.entries())
  • break and continue work inside for...of
  • Avoid for...in on arrays, it iterates indices as strings and includes inherited properties

for...of Loop

Iterate values across arrays, strings, Sets, and any other iterable.

let and const

let andconst are block-scoped alternatives tovar, introduced in ES6 to eliminate common scope and hoisting bugs.

let vs const vs var

Default to const, use let only when you need to reassign, avoid var in modern code.

  • const: block-scoped, must be initialised, cannot be reassigned (the binding is constant, not the value)
  • let: block-scoped, can be reassigned, not hoisted to usable state
  • var: function-scoped, hoisted, leaks out of blocks, causes subtle bugs
  • Objects and arrays declared with const can still be mutated, only the variable binding is locked

let, const, and var

Block scope prevents leaks, const by default, let when reassignment is needed.

Featurevarletconst
ScopeFunctionBlockBlock
ReassignableYesYesNo
HoistedYes (as undefined)Yes (TDZ, unusable)Yes (TDZ, unusable)
Re-declarableYesNoNo
Use todayAvoidWhen neededDefault choice

Knowledge Check

1. What does array destructuring do?

2. What is the output of: const { a = 10 } = {}; console.log(a);

3. What does the spread operator do when used with an array?

4. What do rest parameters collect?

5. Which feature lets you embed expressions inside a string using backticks?

6. What is property shorthand in ES6 object literals?

7. What is the key difference between for...of and for...in?