Destructuring

  • a way of unpacking values from an array or an object into separate variables --- to break a complex data structure down into a simpler data structure like a variable

Arrays

Basic Example

  • standard retrieving of elements without destructuring:
    const arr = [2, 3, 4]
    const a = arr[0]
    const b = arr[1]
    const c = arr[2]
  • we use [] brackets for destructuring arrays
    • when the [] brackets are on the left side of the assignment operator it is for destructuring, rather than assigning
  • with destructuring:
    const [x, y, z] = arr
    console.log(x, y, z);   // 2 3 4
  • the original array is left unchanged
    console.log(arr);       // ▶︎(3) [2, 3, 4]

Expanded Example

starter code:

const restaurant = {
  name: 'Classico Italiano',
  location: 'Via Angelo Tavanti 23, Firenze, Italy',
  categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
  starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
  mainMenu: ['Pizza', 'Pasta', 'Risotto'],
}

Unpacking Specific Elements

  • don't have to unpack all the values from an array --- leave blank spaces for skipped elements
    const [first, second] = restaurant.categories
    console.log(first, second)    // Italian Pizzeria
    const [first, , second] = restaurant.categories
    console.log(first, second)    // Italian Vegetarian

Switching Elements

let [main, , secondary] = restaurant.categories
console.log(main, secondary)    // Italian Vegetarian
  • without destructuring
    const temp = main
    main = secondary
    secondary = temp
    console.log(main, secondary)    // Vegetarian Italian
  • with destructuring
    [main, secondary] = [secondary, main]
    console.log(main, secondary)    // Vegetarian Italian

Destructuring a Returned Array

  • can immediately destructure it --- no need to save it first or anything
    const restaurant = {
      name: 'Classico Italiano',
      location: 'Via Angelo Tavanti 23, Firenze, Italy',
      categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
      starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
      mainMenu: ['Pizza', 'Pasta', 'Risotto'],
      order: function(starterIndex, mainIndex) {
        return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]]
      },
    }
    
    const [starter, mainCourse] = restaurant.order(2, 0)
    console.log(starter, mainCourse)    // Garlic Bread Pizza

Nested Arrays

  • unpacking the nested array
    const nested = [2, 4, [5, 6]]
    const [i, , j] = nested
    console.log(i, j)     // 2 ▶(2) [5, 6]︎ 
  • to unpack the individual values in the nested array we have to do a nested destructuring
    const nested = [2, 4, [5, 6]]
    const [i, , [j, k]] = nested
    console.log(i, j, k)    // 2 5 6

Setting Default Values

  • useful if we don't know the length of the array

(in the following examples pretend we don't know how long the assigned array is)

  • what happens without default values
    // pretend we don't know how long the assigned array is 
    const [p, q, r] = [8, 9]  
    console.log(p, q, r)    // 8 9 undefined
  • with default values set
    const [p = 1, q = 1, r = 1] = [8, 9]  
    console.log(p, q, r)    // 8 9 1
    const [p = 1, q = 1, r = 1] = [8]  
    console.log(p, q, r)    // 8 1 1

Objects

  • uses {} braces instead of the [] brackets used above for arrays

new version of the starter code:

const restaurant = {
  name: 'Classico Italiano',
  location: 'Via Angelo Tavanti 23, Firenze, Italy',
  categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
  starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
  mainMenu: ['Pizza', 'Pasta', 'Risotto'],
  operatingHours: {
    thu: {
      open: 12,
      close: 22,
    },
    fri: {
      open:11,
      close: 23,
    },
    sat: {
      open: 0,  // open 24 hours
      close:24
    },
  },
  order: function(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]]
  }
}

Unpacking Properties

  • order doesn't matter for an object, so no need to skip elements
  • we must have the exact property/key names
const {name, operatingHours, categories} = restaurant
console.log(name, operatingHours, categories)     // Classio Italiano
                                                  // ▶{thu: {...}, fri: {...}, sat: {...}}
                                                  // ▶(4) ["Italian", "Pizzeria", "Vegetarian", "Organic"]

Changing the Property/Key Names

const {
  name: restaurantName,
  operatingHours: hours,
  categories: tags
} = restaurant
console.log(restaurantName, hours, tags)     // Classio Italiano
                                             // ▶{thu: {...}, fri: {...}, sat: {...}}
                                             // ▶(4) ["Italian", "Pizzeria", "Vegetarian", "Organic"]

Setting Default Values

const {menu = [], starterMenu: starters = []} = restaurant
console.log(menu, starters)                  // []
                                             // ▶(4) ["Focaccia", "Buschetta", "Garlic Bread", "Caprese Salad"]
  • most of the time our data won't be hardcoded (it will come from an API, etc) so we won't always know exactly what the data looks like, so it can be helpful to set defaults

Mutating Variables

let a = 111
let b = 999
const obj = {a: 23, b: 7, c: 14}
// we want to overwrite 'a' and 'b' with the new values in the object
  • can't use const {a, b} = obj to destructure because a and b are already assigned
  • don't want to use let {a, b} = obj because it would create new variables instead of using the ones already created
  • {a, b} = obj gives us Uncaught SyntaxError: Unexpected token '=' because when we start a line with a curly brace JS expects a code block --- so we have to wrap the whole thing in parentheses
let a = 111
let b = 999
const obj = {a: 23, b: 7, c: 14}
({a, b} = obj)
console.log(a, b)   // 23 7

Nested Objects

(for the following examples assume `operatingHours has already been unpacked)

  • getting the fri object from operatingHours
    const {fri} = operatingHours
    console.log(fri)      // ▶{open: 11, close: 23}
  • getting open and close from the fri object in the operatingHours object
    const {fri: {open, close}} = openingHours
    console.log(open, close)    // 11 23
  • could also rename the variables while unpacking
    const {
      fri: {open: o, close: c}
    } = openingHours
    console.log(o, c)    // 11 23

Parameters as Objects

  • the function will destructure the object so the params can be used
  • it's nice because you don't need to know the order of the parameters
const restaurant = {
  name: 'Classico Italiano',
  location: 'Via Angelo Tavanti 23, Firenze, Italy',
  categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
  starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
  mainMenu: ['Pizza', 'Pasta', 'Risotto'],
  operatingHours: {
    thu: {
      open: 12,
      close: 22,
    },
    fri: {
      open:11,
      close: 23,
    },
    sat: {
      open: 0,  // open 24 hours
      close:24
    },
  },
  order: function(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]]
  },
  orderDelivery: function ({starterIndex, mainIndex, time, address}) {
    console.log(`Order recieved! ${this.starterMenu[starterIndex]}  and ${this.mainMenu[mainIndex]} will be delivers to ${address} at ${time}`)
  },
}

restaurant.orderDelivery({
  time: '22:30',
  address: 'Via del Sol, 21',
  mainIndex: 2,
  starterIndex: 2,
})

//  Order received! Garlic Bread and Risotto will be delivered to Via del Sol, 21 at 22:30 
  • we can use still set defaults
    const restaurant = {
      name: 'Classico Italiano',
      location: 'Via Angelo Tavanti 23, Firenze, Italy',
      categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
      starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
      mainMenu: ['Pizza', 'Pasta', 'Risotto'],
      operatingHours: {
        thu: {
          open: 12,
          close: 22,
        },
        fri: {
          open:11,
          close: 23,
        },
        sat: {
          open: 0,  // open 24 hours
          close:24
        },
      },
      order: function(starterIndex, mainIndex) {
        return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]]
      },
      orderDelivery: function ({
        starterIndex = 1, 
        mainIndex = 0, 
        time = '20:00', 
        address,
      }) {
        console.log(`Order recieved! ${this.starterMenu[starterIndex]}  and ${this.mainMenu[mainIndex]} will be delivers to ${address} at ${time}`)
      },
    }
    
    restaurant.orderDelivery({
      address: 'Via del Sol, 21',
      starterIndex: 1,
    })
    
    //  Order received! Bruschetta and Pizza will be delivered to Via del Sol, 21 at 20:00 

Copyright © 2022