“Minimizing can be exhilarating. If you continue decluttering, you just might find a zest for life that you didn’t know existed under all that stuff!”
― Lisa J. Shultz, Lighter Living: Declutter. Organize. Simplify.
Introduction
One of the powerful features introduced in ES6 is object destructuring. Basically, it allows us to extract the properties of objects and create new variables from the values of the properties.
This features enables us to create new variables with the same name as the properties of an object, removing redundancy in the code. See the snippet below:
const face = {
eyes: 2,
nose: 1,
ears: 2,
mouth: 1
};
// Without object destructuring
const eyes = face.eyes;
const nose = face.nose;
const ears = face.ears;
const mouth = face.mouth;
// With object destructuring
const { eyes, nose, ears, mouth } = face;
Look at the differences. With object destructuring, we reduced typing “const”, “face”, “=”, and “;” from 4 times to 1 time, “eyes, nose, ears, mouth” reduced from 2 times to 1 time, and “.” to 0 times. It becomes easier to read and understand with the same logic.
With the basics already covered, here are some tricks in object destructuring you should know.
Assign New Names for Destructured Variables
So, I heard that you would like to rename the properties to something else on destructuring? You got it:
const obj = {
propA: 'valA',
propB: 'valB',
propC: 'valC'
};
const {
propA: itemA,
propB: keyB,
propC: resultC
} = obj;
console.log(itemA, obj.propA); // "valA", "valA"
console.log(keyB, obj.propB); // "valB", "valB"
console.log(resultC, obj.propC); // "valC", "valC"
As you can see, itemA
was obj.propA
, keyB
was obj.propB
, resultC
was obj.propC
. The new renamed variables had the same values as the properties of the object.
Set Default Values
If we expect that the object has a certain property, but are unsure whether the property will always exist, it is good practice to put default values on destructuring the object:
const obj = {
propA: 'valA',
propB: 'valB',
propC: 'valC'
};
const {
propA = 'defaultValueA',
propB = 'defaultValueB',
propF = 'defaultValueF'
} = obj;
console.log(propA); // "valA"
console.log(propB); // "valB"
console.log(propF); // "defaultValueF"
On the snippet above, we set some default values to the existing properties obj.propA
and obj.propB
, and also to the non-existing property obj.propF
. propA
and propB
both have the values “valA” and “valB” from the object. But, because propF
did not exist, the default value was set.
Nested Destructuring
What if the object has nested properties? Fear not, for it is also possible to destructure them. See this snippet below:
const obj = {
propA: 'valA',
propB: {
propBA: 'valBA',
propBB: 'valBB'
},
propC: {
propCA: {
propCAA: 'valCAA',
propCAB: {
propCABA: 'valCABA'
}
}
}
};
const {
propA,
propB: { propBA, propBB },
propC: {
propCA: {
propCAA,
propCAB
}
}
} = obj;
console.log(propA); // "valA"
console.log(propBA, propBB); // "valBA", "valBB"
console.log(propCAA); // "valCAA"
console.log(propCAB.propCABA); // "valCABA"
console.log(propC);
// Uncaught ReferenceError: propC is not defined
You know about propA
already, so let’s get to propB
. propB
has two child properties: propBA
and propBB
. Therefore, we would destructure it as const { propB: { propBA, propBB } } = obj;
The pattern is the same with the more nested propC
.
Note that only the value of last branch of the destructured object (propA, propBA, propBB, propCAA, propCAB
) can be accessed. Even though propC
is destructured from obj
, propC
is also destructured to propCA
then destructured again to propCAA
and propCAB
. Because of that, propC
cannot be accessed directly (see the console.log()
), unless it’s called as obj.propC
.
With Rest Operator
Someday in your programming journey, you might find that there are some cases where indefinite properties of an object need to be destructured. And you won’t even know the keys. The one way to do this is by using rest operator (...
). Here is an example:
const obj = {
propA: 'valA',
propB: 'valB',
propC: 'valC',
propD: 'valD',
propE: 'valE'
};
const {
propA,
propC,
...otherProps
} = obj;
console.log(propA); // "valA"
console.log(propC); // "valC"
console.log(otherProps);
/*
{
propB: "valB",
propD: "valD",
propE: "valE"
}
*/
From the example above, we destructured propA
, propC
, and the indefinite otherProps
using the rest operator. As you can see, otherProps
is an object containing the properties propB
, propD
, propE
.
Destructure a Function Parameter
A function parameter which is an object can also be destructured. And one can do it on the parameter directly. See this example below:
const funcDestructure = ({ propA, propB }) => {
console.log(propA); // "valA"
console.log(propB); // "valB"
};
const obj = {
propA: 'valA',
propB: 'valB',
propC: 'valC'
};
funcDestructure(obj);
funcDestructure
has an object parameter, which is also destructured to get propA
and propB
only, just like const { propA, propB } = obj
. Then we can use propA
and propB
like usual.
Conclusion
Object destructuring simplifies extracting properties from an object by a lot. It removes redundancy and improves code readability. In my opinion, this is one of the features in ES6 which JavaScript programmers must use.
Are there any object destructuring tricks I missed? Let me know! Live your code and code your life!
“In this modern world it is easy to be complex but difficult to be simple. At least try to keep your mind simple.”
― Debasish Mridha