Zero. Calling a generator function runs none of its body.
Values are computed lazily, one per next() call, so g is a paused generator holding no results yet.
Even the loop header inside evens has not been evaluated, which is why an argument check written on the first line would not have fired.
Today's unit is about syntax you will use in every file, including destructuring, spread, and the modern operators that go with them.
None of it is conceptually deep, and all of it is unavoidable in modern code. The goal here is fluency rather than insight, so reading these forms becomes automatic.
Unpacking values by shape
Destructuring pulls values out of objects and arrays by describing their shape on the left side of =.
| Form | Example | What it does |
|---|---|---|
| object | const { name, age } = user | grabs by key |
| rename | const { name: userName } = user | key name into userName |
| default | const { role = "student" } = user | used only when undefined |
| array | const [first, second] = list | unpacks by position |
The distinction in the last row is the one to keep straight. Objects match by key and arrays match by position, so variable names matter in one and not the other.
Destructuring exists because JavaScript functions receive bags of named data constantly, including API responses, options objects, and React props.
Picking fields out with repeated user.something lines is pure noise, and the pattern form states which fields the code actually uses.
Nearly every modern file uses it, so reading it has to become automatic. It also works in let, in function parameters, and in for...of headers, which the rest of the lesson covers.
Four flavors in one program
Plain keys, a rename, a default, and array positions.
const user = { name: "Ada", age: 36 }; const { name, age } = user; console.log(name + " is " + age); const { name: who, role = "student" } = user; console.log(who + " / " + role); const [gold, silver] = ["Ada", "Grace", "Linus"]; console.log(gold + " then " + silver);
Output
Ada is 36
Ada / student
Ada then GraceThe rename reads key name into a variable called who, and the colon points from key to variable rather than the other way around.
role is missing from user, so the default supplies "student".
The array pattern ignores "Linus" entirely, which is normal. Extra elements are simply not bound, and asking for a fourth would give undefined.
Positions can be skipped with an extra comma, so const [, second] = list takes only the middle one.
Destructuring a missing key gives undefined rather than throwing, and destructuring null or undefined itself throws a TypeError. const { a } = null fails, which is why defaults on the parameter matter.
Swapping and nesting
Two bonus patterns worth recognizing.
let a = 1; let b = 2; [a, b] = [b, a]; console.log(a + " " + b); const config = { server: { host: "api.dev", port: 443 } }; const { server: { host } } = config; console.log(host);
Output
2 1 api.dev
Array destructuring swaps two variables without a temporary, and object patterns nest to reach inner fields in one line.
The swap needs let rather than const, since both variables are reassigned.
The right side builds a temporary array before either assignment happens, which is why the values do not clobber each other.
The nested pattern binds only host, and server itself is not declared. That surprises people, and the fix is const { server, server: { host } } = config when you want both.
Nesting fails loudly on a missing middle. const { server: { host } } = {} throws, because it tries to destructure undefined, and const { server: { host } = {} } = {} guards against it.
In function parameters
The most common real-world spot is a function that takes an options object.
Destructure right in the parameter list, defaults included.
function connect({ host, port = 80 }) { return host + ":" + port; } console.log(connect({ host: "api.dev" }));
Output
api.dev:80Callers pass named options in any order, and the function body gets clean local variables.
The signature also documents itself. Reading { host, port = 80 } tells you both option names and the default without opening the body.
Named options beat positional parameters once there are more than two or three. connect("api.dev", 80, true, false) is unreadable at the call site, and an options object never is.
Calling connect() with no argument throws here, since there is nothing to destructure. Adding = {} after the pattern makes the whole object optional.
You will see this pattern in nearly every JavaScript codebase and framework, and React function components are the version you will meet most often.
role is null, because defaults only apply when the value is undefined.
Destructuring defaults trigger only for undefined, never for null, 0, "", or false.
null is a real value that someone deliberately stored, so it wins over the default.
The same rule governs default parameters, so function f(x = 1) uses the default for f() and f(undefined) and not for f(null).
This is a favorite interview detail, and it is also a real source of bugs. An API that returns null for a missing field defeats every default you wrote, while one that omits the field entirely works as intended.
The ?? operator in the next lesson follows a friendlier rule and treats both null and undefined as absent, which is often what you actually wanted.
describe
Parameter destructuring with one default.
function describe({ city, country = "unknown" }) { return city + ", " + country; } console.log(describe({ city: "Paris", country: "France" })); console.log(describe({ city: "Atlantis" }));
Output
Paris, France Atlantis, unknown
The whole parameter is a destructuring pattern, and the body is one return line combining the two variables.
The second call omits country, so the default fills in, which is the case the function was written for.
city has no default, so calling describe({}) returns "undefined, unknown" rather than throwing. Required fields are not enforced by destructuring, and a guard in the body is the way to demand one.
Passing extra keys is harmless. describe({ city: "Paris", zip: "75001" }) ignores zip completely, which is what makes options objects easy to extend.
Reordering the keys at the call site changes nothing, since object patterns match by name. That is the whole advantage over positional parameters.