Skip to content

Destructuring and Objects - TIL - 2023-02-26

Posted on:February 26, 2023 at 12:27 PM

Table of Contents

Open Table of Contents

#TIL - Destructuring and Objects

Today’s TodayILearned post is a bit more elaborate and involved, and is one that concerns destructuring and objects.

Destructuring has been one of those concepts in programming that I have always had a vague idea of and would have to google whenever it came up. I’ve been going through a part of the Korean Sinabro JavaScript video course on creating a e-commerce site, which is a three-part series in itself. While watching part 2 of the course, which focused on refactoring the codebase created from part 1, I saw a lot of syntax that involved destructuring objects and functions. It even started from the very first line…

import { setupCounter } from './counter';

To seeing variables being declared like so:

`const { divide, multiply,, getTotalCount } = setupCounter();`;

To even seeing functions have parameters that pass data with {} wrapped around (though this is slightly different from destructuring, I’ve realized):

function multiplyCount({ itemId }) {
  // function code
}

It became really clear to me that I needed a more in-depth understanding of these pieces of code to even determine whether all of these examples involved destructuring or not. With the help of Eunjae, who is the creator of the Korean course Sinabro JavaScript, MDN, FreeCodeCamp, and ChatGPT, I now thankfully have a better grasp of it than before.

Let’s get started on what I’ve learned. Note, this post isn’t a comprehensive overview on destructuring - more so, it will unpack subdomains within the topic that I learned today 😉

What is Destructuring?

Destructuring is a method to easily extract values from arrays, or properties from objects, and assign them to variables that uses a shorthand syntax.

Previously, most examples I’ve seen of destructuring have involved arrays, like this:

const array = [1, 2, 3];

// example of destructuring syntax
const [a, b, c] = array;

Thanks to destructuring, second line of code has easily assigned the values 1, 2, 3 to the variables a, b, and c, respectively.

However, while reviewing the refactored e-commerce codebase from the Sinabro JavaScript course, I realized I was very unfamiliar with examples of destructuring of objects, like the code below:

const exampleObject = { x: 1, y: 2, z: 3 };

// destructuring object
const { x, y, z } = exampleObject;

By destructuring exampleObject, the code extracted values from its properties x, y, and z and assigned to variables of the same name.

So what?

The destructuring syntax is a shorthand, which means that it reduces the amount of code we need to write when we want to extract values and assign them to variables, especially if it involves multiple variables.

Essentially, this destructuring syntax:

const exampleObject = { x: 1, y: 2, z: 3 };

// destructuring object
const { x, y, z } = exampleObject;

Is equivalent to this code snippet:

const exampleObject = { x: 1, y: 2, z: 3 };

const x = exampleObject[x];
const y = exampleObject[y];
const z = exampleObject[z];

That’s a lot of typing and lines of code saved. Thanks, destructuring!

Specific things I learned about destructuring

import statements use destructuring

Remember my most recent TodayILearned post on import and export keywords? Well, turns out that import statements had destructuring syntax!

(Edit on 2023.04.03: I have, since this post, realized that import statements are not ENTIRELY the same as destructuring syntax.)

Destructuring Under the ES Module system, import and export statements allows you to extract specific functions from a module. (Edit one 2023.04.03: Because destructuring syntax and import statements use the curly braces, please forgive me for mistakenly thinking that the two are same). For instance, you have two functions that you’d like to export add and substract:

// myModule.js

export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

You can use the following syntax to extract the said functions from the myModule.js module.

import { add, subtract } from './myModule.js';

By importing functions this way, we can use these functions in our code as if they are defined locally.

Destructuring returned objects

Functions can return objects. You can use destructuring to make working with an object return value more concise. This also applies to returned arrays.

function getUser() {
  return {
    firstName: 'Boyeon',
    lastName: 'Ihn',
    age: 29,
  };
}

// Destructure the object returned by getUser()
const { firstName, lastName, age } = getUser();

console.log(firstName); // "Boyeon"
console.log(lastName); // "Ihn"
console.log(age); // 29

In this example, the getUser() function returns and object with three properties: firstName, lastName, and age. By using destructuring, the firstName property is assigned to a constant named firstName, the lastName property is assigned to a constant named lastName, and so on.

The example above has values that are the primitive Number and String type, but this method of destructuring also works if the property (or key) is holding functions as its value.

One point to note that is strikingly obvious but also not completely intuitive for me is that in order for you to destructure an object belonging to a particular function, the said function must return that object. For instance, if the function getUser() had an object within it but did not return that said object as a value, then destructuring is not possible. The destructuring syntax is used to extract specific properties from the target object, so the function must return it. (Once again, DUH! But something I’ll need to remind myself of).

Ignoring some values while destructuring

If your object of interest has certain values that you are not interested in, you can destructure selectively by using trailing commas. How cool!

function getUser() {
  return {
    firstName: "Boyeon",
    lastName: "Ihn",
    age: 29
  };
}

// Destructure the object returned by getUser() but skipping `lastName`
const { firstName, , age } = getUser();

console.log(firstName); // "Boyeon"
console.log(lastName); // ReferenceError: lastName is not defined
console.log(age); // 29

Because lastName has been ignored from destructuring, logging the lastName would result in a ReferenceError.

Renaming a function or object while destructuring

To rename a function or object that was destructuring, you can use the : operator in the destructuring syntax to assign the function (or property). Consider the following object counter, which has two functions, increment and decrement.

const counter = {
  increment: function () {
    console.log('Incrementing...');
  },
  decrement: function () {
    console.log('Decrementing...');
  },
};

If we want to destructure the object and extract the two functions while also renaming them to inc and dec simultaneously, we can do the following:

// Destructure and rename the functions
const { increment: inc, decrement: dec } = counter;

// Use the renamed functions
inc(); // logs "Incrementing..."
dec(); // logs "Decrementing..."

We can now use the renamed functions inc and dec to call the original functions increment and decrement.

Property value shorthand

One of the reasons I was so confused by this function multiplyCount({ itemId}){} code was because I was not familiar with the property value shorthand syntax that is supported in modern JavaScript.

In short, this shorthand syntax allows you to pass key-value information by just including the key name if the key name and value name are the same when you are creating an object.

For instance, an example:

// Using property value shorthand
const firstName = 'Boyeon';
const lastName = 'Ihn';
const user = { firstName, lastName };
console.log(user); // { firstName: "Boyeon", lastName: "Ihn" }

Notice how when creating the object user, I didn’t have to pass { firstName: firstName } nor { lastName: lastName } and only passed the two property/key names.

This is a syntax that I frequently came across on return statements of functions. For instance:

Example credits to ChatGPT:

function createProductList() {
  const products = [];
  let count = 0;

  function addProduct(product) {
    products.push(product);
    count++;
  }

  function getProductById(id) {
    return products.find(product => product.id === id);
  }

  function updateCount() {
    return count;
  }

  return { updateCount, getProductById };
}

On the very last line, you notice that the createProductList() function returns an object that has two properties: updateCount and getProductById. Both of these properties are functions. This is a shorthand syntax that is equivalent to writing updateCount: updateCount getProductById: getProductById. The shorthand syntax is essentially creating key(or properties) with the same name as the function being assigned, and sets the property value to the value of the function.

So what?

TL;DR

My biggest conclusion and takeaway from studying destructuring as well as the object shorthand is this keyword: Simplicity. The reason why these types of syntax are used so frequently is because they make the code more readable and concise.

Well, at least when you know the longform meaning behind the simplified syntax. If you don’t have background information on these shorthand syntaxes, you’d be as confused as I was prior to reading more on this.

Now that I am more familiar and comfortable with understanding the syntax, I hope to incorporate it within my code for readability and simplicity!

References