JavaScript Core/
Lesson

Working with arrays and objects means constantly extracting values. Before destructuringWhat is destructuring?A shorthand for pulling specific values out of an object or array into their own variables instead of accessing them one by one. existed, you had to write repetitive lines like const name = user.name; const age = user.age; for every property. Destructuring gives you a concise syntax for this, while the spread operatorWhat is spread operator?The three-dot syntax (...) that expands an array or object into its individual elements, commonly used to copy or merge collections. makes copying and merging effortless. Together they eliminate dozens of lines of boilerplateWhat is boilerplate?Repetitive, standardized code that follows a known pattern and appears in nearly every project - like setting up a server or wiring up database connections. code and are used everywhere in modern JavaScript and React.

Object destructuringWhat is destructuring?A shorthand for pulling specific values out of an object or array into their own variables instead of accessing them one by one.

Instead of accessing properties one by one:

const user = { name: "Alice", age: 25, email: "alice@example.com" };

// Old way - repetitive
const name = user.name;
const age = user.age;

// Destructuring - one line
const { name, age, email } = user;

console.log(name);   // "Alice"
console.log(age);    // 25
console.log(email);  // "alice@example.com"

The variable names must match the property names exactly. If you write const { nme } = user, you get undefined because there is no property called nme.

Renaming variables

Sometimes you want a different variable name than the property name:

const { name: userName, age: userAge } = user;

console.log(userName);  // "Alice"
console.log(userAge);   // 25
// name and age are NOT defined - only userName and userAge exist

This is especially useful when destructuring from two objects with overlapping property names, or when a property name conflicts with an existing variable.

Default values

Provide fallbacks for missing properties:

const user = { name: "Alice" };

const { name, age = 18, role = "user" } = user;

console.log(age);   // 18 (default - property was missing)
console.log(role);  // "user" (default)

Defaults only kick in when the value is undefined. If the property exists but is null or 0, the default is not used.

Nested destructuring

Extract values from nested objects:

const user = {
  name: "Alice",
  address: {
    city: "Paris",
    country: "France"
  }
};

const { name, address: { city, country } } = user;

console.log(city);    // "Paris"
console.log(country); // "France"
// note: address itself is NOT defined as a variable
AI pitfall, over-destructuring
AI loves deeply nested destructuring like const { data: { users: [{ name, address: { city } }] } } = response. This is fragile and unreadable. If the API response shape changes even slightly, the entire destructuring breaks with a cryptic error like TypeError: Cannot destructure property 'users' of undefined. Keep destructuring to one or two levels deep. For anything deeper, use intermediate variables: const users = response.data.users then destructure from there. Also watch for AI destructuring properties that might not exist, always add defaults for optional nested values or use optional chaining first.
02

Array destructuringWhat is destructuring?A shorthand for pulling specific values out of an object or array into their own variables instead of accessing them one by one.

Extract array elements by position:

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

const [first, second, third] = colors;

console.log(first);   // "red"
console.log(second);  // "green"
console.log(third);   // "blue"
PatternSyntaxResult
Basicconst [a, b] = arrFirst two elements
Skip itemsconst [a, , c] = arrFirst and third
Restconst [a, ...rest] = arrFirst + remaining array
Defaultsconst [a = 1] = []Fallback if missing
Swap[a, b] = [b, a]Swap two variables
// Skip elements with commas
const [first, , third] = colors;

// Rest pattern - capture remaining elements
const [head, ...tail] = colors;
console.log(head);  // "red"
console.log(tail);  // ["green", "blue"]

Array destructuring is commonly used with functions that return arrays, like React's useState:

const [count, setCount] = useState(0);
// count = 0, setCount = the setter function
03

Spread operatorWhat is spread operator?The three-dot syntax (...) that expands an array or object into its individual elements, commonly used to copy or merge collections.

The spread operator (...) expands an iterable into individual elements. It looks identical to the restWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. syntax but works in the opposite direction: rest collects, spread expands.

Spreading arrays

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

const combined = [...arr1, ...arr2];  // [1, 2, 3, 4, 5, 6]
const copy = [...arr1];               // [1, 2, 3] - shallow copy
const extended = [0, ...arr1, 4];     // [0, 1, 2, 3, 4]

Spreading objects

const defaults = { theme: "light", notifications: true };
const userPrefs = { theme: "dark" };

// Merge objects - later properties overwrite earlier ones
const settings = { ...defaults, ...userPrefs };
console.log(settings);  // { theme: "dark", notifications: true }
Important
Spread creates shallow copies. Nested objects and arrays are still referenced, not duplicated. For deep copies, use structuredClone().
04

RestWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. parameters in functions

Rest syntax (also ...) collects remaining arguments into an array:

function sum(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}

console.log(sum(1, 2, 3));  // 6
console.log(sum(10, 20));   // 30
05

Practical patterns

Function parameter destructuringWhat is destructuring?A shorthand for pulling specific values out of an object or array into their own variables instead of accessing them one by one.

// Instead of accessing user.name, user.age inside the function:
function greet({ name, age }) {
  return `Hello, ${name}! You are ${age}.`;
}

greet({ name: "Alice", age: 25 });  // "Hello, Alice! You are 25."

Cloning with property updates

This pattern is extremely common in React for updating state immutably:

const user = { name: "Alice", age: 25, city: "Paris" };

// Create new object with updated age
const updated = { ...user, age: 26 };

console.log(updated);  // { name: "Alice", age: 26, city: "Paris" }
console.log(user);     // { name: "Alice", age: 25, city: "Paris" } - unchanged

Swapping variables

let a = 1;
let b = 2;

[a, b] = [b, a];  // a = 2, b = 1
06

Quick reference

PatternSyntaxWhat it does
Object destructuringconst { a, b } = objExtract named properties
Renameconst { a: x } = objExtract a into variable x
Defaultconst { a = 1 } = objFallback if property missing
Array destructuringconst [a, b] = arrExtract by position
Rest (array)const [a, ...rest] = arrCollect remaining items
Rest (object)const { a, ...rest } = objCollect remaining properties
Spread (array)[...arr1, ...arr2]Merge arrays
Spread (object){ ...obj1, ...obj2 }Merge objects (shallow)
Rest paramsfunction f(...args)Collect all arguments