creating objects

2019-10-29

 | 

~3 min read

 | 

440 words

The other day I came across a pattern for creating objects I couldn’t quite understand. The code looked a little like this:

const objA = { /* … */ }
const objB = { /* … */ }
const objC = { /* … */ }const newObj = Object.assign(Object.create(objA), objB, objC)

My confusion was around why we would use Object.create. Wouldn’t I end up with an object with all of the same properties if I excluded the Object.create?

To help myself understand, I played around with a few different ways for creating the newObj.

Object.Create vs {} vs Spread

In creating the objects, I thought about three different ways for creating an object:

  1. Object.assign(Object.create(a), b)
  2. Object.assign({}, a, b)
  3. {...a, ...b}

Here’s what that looks like:

const personPrototype = {
  eyes: 2,
  greet() {
    return `Hi! My name is ${this.name}!`
  },
}

const stephen = {
  name: "Stephen",
}

const justin = {
  name: "Justin",
}

const jim = {
  name: "Jim",
}

const stephenPerson = Object.assign(Object.create(stephen), personPrototype)
const justinPerson = Object.assign({}, justin, personPrototype)
const jimPerson = { ...jim, ...personPrototype }

The second and third approaches are the same, however, there’s a major distinction between them and the first approach.

The stephenPerson object has two properties (eyes, and greet), while justinPerson and jimPerson have a name property as well.

But wait…

How does the greeting know the name’s Stephen if it’s not on the object? Because it’s on the object’s prototype.

Why This Matters

When it comes to updating the name then, the stephenPerson has more options than justinPerson or jimPerson.

We can add a name property directly to stephenPerson which would then be referenced by the greeting:

Alternatively, we could update stephen directly:

This does not work for the justin or jim objects because justinPerson and jimPerson have no reference to those objects any more.

Conclusion

Use Object.create if you want to be able to continue to manage the object separately. In our example above, we would be able to continue to update objA directly and have those values accessible in our newObj because of prototypal inheritance. The values would be present on newObj’s prototype and therefore if they don’t appear directly on newObj, we would look to its prototype.

If the management of objA directly is not a primary concern, and you’re comfortable updating the newObj going forward, however, Object.create is unnecessary - particularly because if you assign a property to newObj that is present on objA, it will make the property on objA inaccessible unless you go through __proto__ directly.



Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!