DEV Community

Cover image for If you Wannabe (assigned) in my JS Object: Conditionally adding properties to JS Objects
Jonathan Silvestri
Jonathan Silvestri

Posted on

If you Wannabe (assigned) in my JS Object: Conditionally adding properties to JS Objects

If you've worked with objects in JavaScript, you may have come across situations where you need to optionally add values to an existing object. To illustrate my example, I'd like to welcome the Spice Girls to this corner of the internet.

Traditionally, you could assign values like this:

  function relationship(name, youGotWithMyFriends) {
    var interestedParty = {
      name: name
    }

    if(youGotWithMyFriends) {
      interestedParty.lover = true
    }

    return interestedParty
  }

  // Later in our code...
  var person = relationship('person', false)
  console.log(person) // { name: 'person'}
  var nextPerson = relationship('match', true)
  console.log(nextPerson) // { name: 'match', lover: true }

As the Spice Girls clearly outlined for us in 'Wannabe', you'll need to get with their friends to be a lover.

Now, one could argue that you can add the lover property to all the objects and have it be false by default. Totally valid, but for the purposes of this example, let's say that we don't want a lover property unless it is true, and keep going down this path.

What if we had to add further properties with additional guard clauses that prevent assigning falsey values to our object? it might get a little unfun to have to write if statements over and over.

Modernizing our approach, with ES6

With ES6, we gained access to the spread syntax. Useful for taking values from one collection and spreading them into another one, but our above example can also leverage this syntax!

Let's have another chat with the Spice Girls and see what they think about our fun new ES6 functionality...

  function relationship(name, youGotWithMyFriends) {
    return {
      name,
      ...(youGotWithMyFriends && { lover: true }) // !!!
    }
  }

  // Later in our code...
  const person = relationship('person', false)
  console.log(person) // { name: 'person'}
  const nextPerson = relationship('match', true)
  console.log(nextPerson) // { name: 'match', lover: true }

We get the same result! But umm...Spice Girls...

What's going on?

Let's go over our line that leverages the spread operator to add that property to the return object, ...(youGotWithMyFriends && { lover: true }), and talk a bit about what's happening.

In the case of youGotWithMyFriends being true, you end up continuing in your code and hitting the { lover: true } piece, and because the spread syntax is in use, it will spread the contents of that object to the object it is nested in, giving you the second console.log value!

But what happens if that boolean is false? Can you "spread" false on to an object without an error being thrown?

The spread syntax can be thought of as a shorthand, more straightforward Object.assign function call. When you utilize it, it is like calling the function as follows:

Object.assign(targetObject, thingsToAddToTarget)

We can see how our first example works when we use Object.assign, as thingsToAddToTarget will just be our new object. But let's talk about the case of false being passed as the second argument:

const targetObject = {}
Object.assign(targetObject, false) // returns {}

Sometime during Object.assign's implementation cycle, the team working on it decided that if the second argument is not an indexed value, instead of failing loudly, it will ignore what is passed in and return your original object, unmodified! Try passing a number, a null, or even undefined in your browser console as a second argument to see for yourself :).

I hope you enjoyed this little example of leveraging a cool ES6 feature, and that you can find use-cases in your code today.

Top comments (8)

Collapse
 
michaeltharrington profile image
Michael Tharrington

Haha!! I read this title and wondered... hmmm 🤔... is this a Spice Girl reference? Yep, this is a Spice Girl reference. 👏

However, I'm pretty dang sure it's youGottaGetWithMyFriends as it's playing over and over in my head right now. 😂

Collapse
 
silvestricodes profile image
Jonathan Silvestri

Also yeah that's the lyric, but for the sake of making the example work, past tense :P

Collapse
 
michaeltharrington profile image
Michael Tharrington

solid point 👍

Collapse
 
silvestricodes profile image
Jonathan Silvestri

I should probably title this a little differently to better encapsulate what lies in the post.

Collapse
 
parasharrajat profile image
Rajat Parashar • Edited

Marvelous post..I have been into these situations for so long but thought of what is under the hood in spread operator. And really Object.assign does that, amazing!. Thanks for sharing. Now on you are on my following list.

Collapse
 
the_riz profile image
Rich Winter

Does using the spread {..._} operator or Object.assign() duplicate the object in memory instead of simply extending the existing one?

Collapse
 
silvestricodes profile image
Jonathan Silvestri

Good question! Object.assign does not duplicate the target object in memory - it adds on to the existing object, and in the case of clashing keys, the keys and their values from the added object will overwrite the existing one.

With that being the case, the same answer applies to the spread operator.

Collapse
 
jeremysgranger profile image
Jeremy Granger

Wow, this is excellent! Could've used this a few weeks ago at work. Time to refactor! :D