# Destructuring

## 1. Array Destructuring

Extracts values by **position**.

```js
const [first, second] = [10, 20, 30];       // first=10, second=20 (30 is ignored)
const [, , third] = [10, 20, 30];             // skip positions with empty commas -> third=30
const [head, ...tail] = [1, 2, 3, 4];         // head=1, tail=[2,3,4]
const [a = 100, b = 200] = [undefined, 5];    // a=100 (default used), b=5
```

## 2. Object Destructuring

Extracts values by **key name**, order-independent.

```js
const user = { name: "Ana", age: 30, city: "Berlin" };

const { name, age } = user;                    // name="Ana", age=30
const { name: userName } = user;                // rename while destructuring -> userName="Ana"
const { role = "guest" } = user;                 // role="guest" (default, key doesn't exist)
const { city: userCity = "Unknown" } = user;      // rename + default combined
```

![The user object's name and age keys mapped by name into two new variables, city left untouched](diagrams/01-destructure-mapping.svg)

## 3. Nested Destructuring

```js
const response = {
  data: { user: { id: 1, profile: { avatar: "url.png" } } },
  status: 200,
};

const {
  status,
  data: {
    user: { id, profile: { avatar } },
  },
} = response;
// status=200, id=1, avatar="url.png"
// NOTE: `data` and `user` themselves are NOT created as variables here —
// only the leaf names actually pulled out (status, id, avatar) become bindings.
```

## 4. Destructuring Function Parameters

```js
function createUser({ name, age = 18, roles = [] }) {
  return { name, age, roles };
}
createUser({ name: "Ana" }); // { name: "Ana", age: 18, roles: [] }

function move({ x, y } = { x: 0, y: 0 }) { // default for the WHOLE object if none is passed
  return [x, y];
}
move(); // [0, 0]
```

This is the standard pattern for "named arguments" / options objects in JavaScript, replacing long positional parameter lists.

## 5. Swapping Variables

```js
let a = 1, b = 2;
[a, b] = [b, a]; // a=2, b=1 — no temporary variable needed
```

## 6. Destructuring in Loops

```js
const entries = [["a", 1], ["b", 2]];
for (const [key, value] of entries) {
  console.log(key, value);
}

const users = [{ id: 1, name: "Ana" }, { id: 2, name: "Leo" }];
for (const { id, name } of users) {
  console.log(id, name);
}
```

## 7. Combining with Rest

```js
const { id, ...rest } = { id: 1, name: "Ana", age: 30 };
// id=1, rest={ name: "Ana", age: 30 }

const [first, ...others] = [1, 2, 3];
// first=1, others=[2, 3]
```

Rest must always come **last** in both array and object destructuring patterns.

## Under the Hood: Destructuring Is Pure Syntax, Not a Runtime Feature

Destructuring adds no new capability to the engine — it's parsed and compiled down to exactly the sequential property/index accesses you'd write by hand. There is no special "destructuring engine" doing anything smarter than that.

```js
const { name, age } = user;
// compiles down to roughly:
const name = user.name;
const age = user.age;
```

```js
const [first, second] = arr;
// compiles down to roughly:
const first = arr[0];
const second = arr[1];
```

### This means nested destructuring costs exactly what manual chaining costs

```js
const { data: { user: { profile: { avatar } } } } = response;
// costs exactly the same as:
const avatar = response.data.user.profile.avatar;
```

Every one of those accesses is a real property lookup, subject to the exact same hidden-class / inline-cache machinery from the Prototypes and Prototype Chain topics — destructuring doesn't skip that machinery or make deeply nested access any cheaper than writing it out by hand. Its entire value is **readability at the source level**, with zero runtime cost difference either way.

### Destructuring a primitive triggers temporary auto-boxing

```js
const { length } = "hello"; // length = 5
```

Strings aren't objects, but `.length` is a property access — the engine temporarily wraps the primitive in its corresponding wrapper object (`String`, `Number`, `Boolean`) just long enough to perform the lookup, then discards the wrapper. This is the same auto-boxing mechanism that lets `"hello".toUpperCase()` work despite strings being primitives — destructuring a primitive simply routes through the same mechanism section 1's array/object examples don't need, since arrays and objects are already real objects.

### Why destructuring `null`/`undefined` throws instead of silently failing

```js
const { a } = null; // TypeError: Cannot destructure property 'a' of 'null' as it is null.
```

Property access fundamentally requires a real object (or something auto-boxable) to read from — `null`/`undefined` have no properties and can't be boxed into anything, so the underlying property-read operation fails exactly the way `null.a` would fail if you wrote it manually. This is *why* the common fallback pattern `function f({ a } = {})` works: it doesn't make destructuring "safer" in general, it just ensures the value being destructured is never `null`/`undefined` in the first place.

## 8. Common Pitfalls

1. **Destructuring `undefined`/`null` directly throws** — `const { a } = undefined;` is a `TypeError`, not `a = undefined`. Always ensure a fallback object (`= {}`) when the source might be missing.
2. **Renaming syntax direction confusion** — `{ name: userName }` reads "take `name`, call it `userName`" — the source key is on the left of the colon, the new local name on the right. Easy to reverse by mistake.
3. **Defaults only trigger on `undefined`**, exactly like function default parameters — `null` does not trigger a destructuring default.
4. **Forgetting nested destructuring doesn't create intermediate variables** — only the innermost names you explicitly write become bindings.
5. **Destructuring in a function signature swallowing `undefined`** — calling `createUser()` with no argument at all throws unless the whole parameter has a default: `function createUser({ name } = {})`.

## 9. Quick Reference

```
[a, b] = arr           → positional
{a, b} = obj            → by key
{a: renamed} = obj      → rename
{a = default} = obj     → default if undefined
{a, ...rest} = obj      → rest must be last
```
