Day 4: New Object Features

If you have ever constructed objects in JS it can be a repetitive experience. One must type the property name followed by value, over and over and over until one is done. At least it's not JSON.

ES6 gets rid of this repetition hell and allows you to do the following:

const name = 'Ferguson'
const weight = 90001
const cat = {
  name,
  weight,
}

Defaults

Remember when you had to check for undefined variables every time just so you could set a default?

var planets = {
  druidia: {
    air: 100,
  }
}
function stealAirFromPlanet(planetId) {
  if (planetId === undefined) {
    planetId = 'druidia'
  }

  return planets[planetId].air
}
console.log(stealAirFromPlanet())
Try in REPL

This was crazy! It was enough to make someone switch to CoffeeScript! Thankfully ES6 comes with defaults. With ES6 the above becomes:

const planets = {
  druidia: {
    air: 100,
  }
}
const stealAirFromPlanet = (planetId='druidia') => {
  return planets[planetId].air
}
stealAirFromPlanet()
Try in REPL

Destructuring

Look over any ES5 codebase and you will find it littered with lines like the following:

function addUser(user) {
  var name = user.name
  var cats = user.cats
  var car  = user.car
  var dogs = user.dogs
  var handshakeSkillLevel = user.handshakeSkillLevel
  var memeSpeed = user.memeSpeed
}

Getting data out of objects is one of the most repetitive tasks a developer has to do. We spend almost as much time on it as we do choosing a new syntax theme or reading HN and getting angry at the internet.

In ES6 we no longer have to deal with this. In ES6 we can destructure an object in a single line like this:

const user = {
  name: 'Bob',
  pets: [{
    name: 'Gil',
    type: 'goldfish'
  }],
  fears: 'everything',
  psychiatrist: 'Dr. Marvin',
}

const { name, fears, psychiatrist } = user
console.log(name, fears)
Try in REPL

It works for arrays too:

const mysteriousNumbers = [4625, 6174]

const [uvb76, kaprekar] = mysteriousNumbers
console.log(uvb76)
kaprekar
Try in REPL

We can also destructure an object passed as an argument:

const user = {
  name: 'M-O',
  purpose: 'Clean all the things!',
  likes: ['Maintaining order', 'Cleaning'],
  dislikes: ['Messes', 'Dirt'],
}

const printUserLikes = ({ name, likes }) => {
  console.log(`My name is ${name} and I like; ${likes.join(' and ')}`)
}
printUserLikes(user)
Try in REPL

It works for returns too:

const getUserById = (id) => {
  const usersById = {
    1: {
      name: 'Craig Christ',
      family: ['Jesus', 'God', 'That Marry Chick']
    },
    2: {
      name: 'Biff',
      pals: ['Jesus']
    }
  }

  return usersById[id]
}
const { name } = getUserById(1)
name
Try in REPL

Destructuring is awesome!

ES6 Rest and Spread

Do you ever feel like you are tired? Like you just cant get enough done in the day? Like your objects take too long to construct? Do you ever feel like you spend your days merging objects? Are you tired of importing lodash every time you need to merge a thing into another thing? If the answer is yes, then ES6 Rest and Spread might be for you. Ask Dan Abramov if rest and spread is for you.

Rest

ES6 has a new feature called rest. It is used for those scenarios where you used to use arguments. Take for example a cat function, where we want to accept multiple cats as individual arguments:

const printCatNames = (cat1, cat2, cat3) => {
  console.log(cat1.name)
  console.log(cat2.name)
  console.log(cat3.name)
}
printCatNames({ name: 'Ferguson' }, { name: 'Snowball' }, { name: 'Cat Damon' })
Try in REPL

Instead of writing out all the cats we can simply use rest to turn these arguments into an array:

const printCatNames = (...cats) => {
  cats.forEach((cat) => {
    console.log(cat.name)
  })
}
printCatNames({ name: 'Ferguson' }, { name: 'Snowball' }, { name: 'Cat Damon' })
Try in REPL

Spread

ES6 provides an awesome feature called spread. You are going to use this a ton. It takes properties from one object and allows you to spread them on another. It is like a simple merge. It looks like this:

const buildACat = (myCatProps) => {
  const defaultCat = {
    name: 'Awesome Cat',
    powers: ['knocks things over', 'looking adorable'],
  }  

  return {
    ...defaultCat,
    ...myCatProps,
  }
}
const myCat = buildACat({ name: 'Fluffysaurus' })
myCat
Try in REPL

Now onto Day5!