Destructuring on nested objects in ES6

Destructuring on nested objects in ES6

Destructuring simply implies breaking down a complex structure into simpler parts. In JavaScript, this complex structure is usually an object or an array. With the destructuring syntax, you can extract smaller fragments from arrays and objects. Destructuring syntax can be used for variable declaration or variable assignment. You can also handle nested structures by using nested destructuring syntax.

Let’s start with the basics. Here is a simple example that extracts a single prop.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {name} = user;
console.log(name); //prints: Fred

Here is another example that extracts the props, but assigns it to a different name.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {name: callSign} = user;
console.log(callSign); //prints: Fred

Destructuring also works for nested objects.

const user = {
  id: 339,
  name: 'Fred',
  age: 42,
  education: {
    degree: 'Masters'
  }
};
const {education: {degree}} = user;
console.log(degree); //prints: Masters

But what happens when the nested object is missing?

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {degree}} = user;  // TypeError: Cannot match against 'undefined' or 'null'.

We can solve this by adding a default value.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {degree} = {}} = user;
console.log(degree); //prints: undefined

But what happens when you nest even more?

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {school: {name}} = {}} = user;  // TypeError: Cannot match against 'undefined' or 'null'.

We can continue to add more default values to solve this problem. But what is interesting is there is more than one solution.

The first solution is to add a default value for school.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {school: {name} = {}} = {}} = user;
console.log(name); //prints: undefined

The other solution is to expand the education default value.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {school: {name}} = {school: {}}} = user;
console.log(name); //prints: undefined

Either solution seems acceptable, but consider case where you want to add a default for the school name.

In the first solution we have.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {school: {name = 'Dunno'} = {}} = {}} = user;
console.log(name); //prints: Dunno

And in the second solution it will be.

const user = {
  id: 339,
  name: 'Fred',
  age: 42
};
const {education: {school: {name}} = {school: {name: 'Dunno'}}} = user;
console.log(name); //prints: Dunno

Which solution you should use depends on what you are trying to do. Is it more likely individual fields will be omitted or whole nested objects?