Tan-Aki
Tan-Aki

Reputation: 307

Composition with spread objects

I watched a tutorial on composition, and it makes you compose objects like this:

const eater = (state) => ({
  eat(amount) {
    console.log(state.name + ' is eating');
    state.energy += amount;
  }
});

// using a factory
const Dog = (name, energy, breed) => {
  let dog = {
    name,
    energy,
    breed
  };
  return Object.assign(dog, eater(dog));
};

const leo = Dog('Leo', 10, 'Pug');
leo.eat(10); // Leo is eating
console.log(leo.energy); // 20

I was wondering if you could do something like that instead, and if there are any downsides to doing it like that:

const eater = {
  eat(amount) {
    console.log(this.name + ' is eating');
    this.energy += amount;
  }
};

const Dog = (name, energy, breed) => {
  let dog = {
    name,
    energy,
    breed,
    ...eater
  };
  return dog;
};

const leo = Dog('Leo', 10, 'Pug');
leo.eat(10); // Leo is eating
console.log(leo.energy); // 20

As you can see, instead of creating and assigning a function to the object, with Object.assign, I create another object eater with a method, then I spread that eater object and add it to the dog object being created inside the factory.

So, is there anything wrong with doing it like that?

Thank you!

Upvotes: 2

Views: 252

Answers (1)

FZs
FZs

Reputation: 18619

These two approaches are very similar. Both are workable & good ways.

Here are the differences:

  • The first approach: eater is a factory function

    • New eater object and eat function is created for each dog
    • eat method is bound:

      let leoEat = leo.eat;
      leoEat(10); //works
      
  • The second approach: eater is an object

    • The eater object and the eat function are reused
    • eat isn't bound:

      const leo = Dog('Leo', 10, 'Pug');
      const animal = {name: 'Animal', energy: 0};
      leo.eat.call(animal, 30); // Animal is eating
      console.log(animal.energy); // 30
      console.log(leo.energy); // 10
      
  • The third approach (yes, there is!): Eater and Dog are classes

    • The eat function is reused
    • eat isn't bound
    • Makes use of prototypes
    • Doesn't support multiple inheritance

class Eater {
  eat(amount) {
    console.log(this.name + ' is eating');
    this.energy += amount;
  }
};

class Dog extends Eater{
  constructor (name, energy, breed) {
    super();
    Object.assign(this, {
      name,
      energy,
      breed
    })
  }
};

const leo = new Dog('Leo', 10, 'Pug');
leo.eat(10); // Leo is eating
console.log(leo.energy); // 20
console.log(leo instanceof Dog) //true
console.log(leo instanceof Eater) //true

Upvotes: 4

Related Questions