EXERCISE
1You can destructure directly in function parameters. Instead of passing an entire object and picking it apart inside, you extract what you need right in the parameter list.
Destructuring works in a parameter list, which is where it changes how functions are called rather than just shortening a line.
function greet({ name, city }) {
return name + " from " + city;
}
console.log(greet({ name: "Sara", city: "Dubai" })); // "Sara from Dubai"
The function takes one object and names the parts it needs. Compare that with the positional version:
function greet(name, age, city, country, isActive) {
return name + " from " + city;
}
greet("Sara", 28, "Dubai", "UAE", true);
At the call site, every argument is a value with no label. Getting two of them the wrong way round is silent if they are the same type, and adding a parameter in the middle means finding every call. With an object, each value is named where it is passed and the order does not matter.
Defaults go in the pattern:
function connect({ host, port = 5432, secure = true }) {
return host + ":" + port + (secure ? " (tls)" : "");
}
console.log(connect({ host: "db.local" })); // "db.local:5432 (tls)"
The defaults live in the signature, so the function's expectations are visible without reading the body.
Calling with nothing needs a default for the whole parameter:
function connect({ host = "localhost", port = 5432 } = {}) {
return host + ":" + port;
}
console.log(connect()); // "localhost:5432"
Without the trailing = {}, calling connect() tries to destructure undefined and throws. That one is easy to miss, because the function looks like it has defaults for everything.
The same works on arrays, which is how you take apart a pair:
function distance([x1, y1], [x2, y2]) {
return Math.hypot(x2 - x1, y2 - y1);
}
console.log(distance([0, 0], [3, 4])); // 5
Rest collects whatever you did not name:
function render({ id, ...attributes }) {
return { id, count: Object.keys(attributes).length };
}
console.log(render({ id: 1, color: "red", size: "lg" })); // { id: 1, count: 2 }
This is the standard way to pull one value out of a configuration object and pass everything else along untouched.
Pro Tip: Once a function has more than two parameters, or any boolean parameter, an options object is usually the better signature.
save(data, true, false)tells the reader nothing;save(data, { overwrite: true, backup: false })tells them everything.