Destructuring
Destructuring unpacks the values you need from an object or an array into variables in one line, with defaults for anything missing and new names when you want them.
Apprentice · JavaScript · Updated
After this lesson you can
- Unpack an object's properties into variables with destructuring, using defaults and new names
- Unpack an array's items into variables by position with array destructuring
Key takeaways
- Object destructuring takes properties out by key:
const { name, species } = pet;makes two variables named after the keys. - Give a default with
=for a property that might be missing, and a new name with:, as in{ name: petName }. - A default is used only when the value is
undefined. A real value such as 0 or an empty string is kept. - A function can destructure the object it's given right in its parameters, so its first line can get straight to work.
- Array destructuring takes items out by position:
const [first, second] = traits;. A gap with commas skips an item.
Open almost any modern JavaScript project, a React app, a Node server, a browser extension, and within the first few lines you'll see something like const { name, email } = user;. That's destructuring, and once you can read it, a lot of real-world code stops looking like a puzzle. You'll use it whenever an object or an array arrives with more than you need, such as a pet profile from the server when your page only shows the name and age, and you want those values in plain variables.
Unpacking a moving box
When you unpack a moving box labeled Kitchen, you don't carry the whole box to every cupboard. You take out the items you need, by what they are: the kettle, the mugs. The rest can stay in the box.
Object destructuring does that with an object. On the left of the =, curly braces list the keys you want; on the right is the object to take them from. JavaScript makes one variable for each key, named after it:
const pet = { name: 'Mochi', species: 'cat', ageYears: 2, vaccinated: true };
// The long way would be two lines:
// const name = pet.name;
// const species = pet.species;
const { name, species } = pet;
console.log(name);
console.log(species);
Mochi
cat
Read const { name, species } = pet; as "make constants name and species from pet". The braces here don't build an object: on the left of =, they unpack one. The order inside the braces doesn't matter, because each variable is matched to its key by name. Asking for a key the object doesn't have gives that variable undefined, the same as pet.color would.
Defaults and new names
Two small additions make destructuring fit real data.
- A default, written with
=, is used when the property is missing:adoptionFee = 75means "use the pet's fee, or 75 if the form doesn't have one". - A new name, written with a colon
:, unpacks a key into a variable with a different name.name: petNameis read "name, as petName". It helps whennamewould clash with another variable, or isn't clear enough on its own.
const pet = { name: 'Mochi', species: 'cat', ageYears: 2 };
const { name: petName, adoptionFee = 75, nickname = 'none yet' } = pet;
console.log(petName);
console.log(adoptionFee);
console.log(nickname);
Mochi
75
none yet
Watch the direction of the colon: the key from the object comes first, the new variable's name second. After name: petName, there's a variable petName, and no variable name; using name would stop with ReferenceError: name is not defined.
A default kicks in only when the value is undefined, which is what a missing property gives. If Mochi's form said adoptionFee: 0 (a free adoption day), adoptionFee would be 0, not 75. Zero is a real answer, so JavaScript keeps it.
Try it. In your objects-practice folder, make unpack.js with a pet object that has no adoptionFee. Destructure name as petName and adoptionFee with a default of 50, and print both. Then add adoptionFee: 0 to the object and run it again.
Destructuring in a function's parameters
A function that gets a whole object often needs only a few of its properties. Instead of writing pet.name, pet.species and pet.ageYears over and over, the function can destructure the object right where its parameters are listed (the names in a function's parentheses that receive what it's called with). Defaults work here too:
function profileLine({ name, species, ageYears, adoptionFee = 75 }) {
return `${name} (${species}, age ${ageYears}): adoption fee ${adoptionFee}`;
}
const biscuit = { name: 'Biscuit', species: 'dog', ageYears: 3, adoptionFee: 120 };
const mochi = { name: 'Mochi', species: 'cat', ageYears: 2 };
console.log(profileLine(biscuit));
console.log(profileLine(mochi));
Biscuit (dog, age 3): adoption fee $120
Mochi (cat, age 2): adoption fee $75
The caller still passes one whole object, profileLine(biscuit). The braces in the parameter list unpack it as it arrives. (In ${adoptionFee}, the first $ is a plain dollar sign that gets printed; the ${ } after it is the template literal's slot for the value.)
Array destructuring: unpacking by position
An array's items have no labels, only positions. So array destructuring uses square brackets on the left of =, and matches variables to items by their place in line: the first variable gets the first item, the second gets the second, and so on.
- A comma with no name in front of it skips an item.
- A default with
=covers an item that isn't there.
const traits = ['loves fetch', 'good with kids', 'snores'];
const [first, second] = traits;
const [, , third] = traits;
const [top, , , fourth = 'no fourth trait'] = traits;
console.log(first);
console.log(second);
console.log(third);
console.log(top, '|', fourth);
loves fetch
good with kids
snores
loves fetch | no fourth trait
const [, , third] = traits; reads "skip, skip, then third". Since items are matched by position, the names can be anything you like; choose names that say what each position means.
A neat trick that comes from this: swapping two variables in one line, with no temporary variable. The two volunteers on dog-walking duty trade shifts:
let morningWalker = 'Sam';
let eveningWalker = 'Priya';
[morningWalker, eveningWalker] = [eveningWalker, morningWalker];
console.log(`Morning: ${morningWalker}, evening: ${eveningWalker}`);
Morning: Priya, evening: Sam
Tidying up the entries loop
The lesson What Is an Object looped over Object.entries(pet) and read each entry as entry[0] and entry[1]. Each entry is a two-item array, so array destructuring can unpack it right in the loop, with names that say what they are:
const pet = { name: 'Juniper', species: 'dog', ageYears: 7 };
for (const [key, value] of Object.entries(pet)) {
console.log(`${key}: ${value}`);
}
name: Juniper
species: dog
ageYears: 7
You'll see this exact loop in a lot of real code. It's the standard way to walk through every property of an object.
Try it. In unpack.js, make an array of three things you'd pack for a road trip. Destructure the first into mustHave and skip to the third as niceToHave, then print a sentence with both.
Check yourself
2 questions to try on the lesson page.
So what
Destructuring is how modern JavaScript says "I need these parts". You'll read it in nearly every codebase and every framework, and writing it yourself makes your functions shorter and clearer about what they use.