0

i was looking at a blog on object composition and it showed this code here:

const canSayHi = self => ({
  sayHi: () => console.log(`Hi! I'm ${self.name}`)
});
const canEat = () => ({
  eat: food => console.log(`Eating ${food}...`)
});
const canPoop = () => ({
  poop: () => console.log('Going to ...')
});

// Combined previous behaviours
const socialBehaviors = self => Object.assign({}, canSayHi(self), canEat(), canPoop());

const alligator = name => {
  const self = {
    name
  };

  const alligatorBehaviors = self => ({
    bite: () => console.log("Yum yum!")
  });

  return Object.assign(self, socialBehaviors(self), alligatorBehaviors(self));
};


const jack = alligator("jack");

When you go to access the jack alligator, you can of course access the name property on jack. What if i wanted this property to be private, so that jack.name returned undefined. I am assuming this would require a closure but am unsure of the best/cleanest way to do it, or simply the conventional way it is done.

I understand that you could just not pass self to object.assign, but what if you had in self a mixture of variables that you wanted some to be private and some to be public? I would have thought the solution here would be to have a 'state' literal with all the private variables and a 'base' literal that had all the public variables, if you wanted to access anything in the base literal you would then need to use this in the other objects in objects.assign.

Dom
  • 1,232
  • 1
  • 10
  • 20

2 Answers2

1

Every internal function that uses the .name is passed self explicitly while the object is being constructed, so you can just return

Object.assign({}, ...

instead of

Object.assign(self, ...

and the returned object will not have a name property.

const canSayHi = self => ({
  sayHi: () => console.log(`Hi! I'm ${self.name}`)
});
const canEat = () => ({
  eat: food => console.log(`Eating ${food}...`)
});
const canPoop = () => ({
  poop: () => console.log('Going to ...')
});

// Combined previous behaviours
const socialBehaviors = self => Object.assign({}, canSayHi(self), canEat(), canPoop());

const alligator = name => {
  const self = {
    name
  };

  const alligatorBehaviors = self => ({
    bite: () => console.log("Yum yum!")
  });

  return Object.assign({}, socialBehaviors(self), alligatorBehaviors(self));
};


const jack = alligator("jack");
console.log('jack.name:', jack.name);
jack.bite();
jack.eat('somefood');
jack.sayHi();
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • What if you had a mixture of variables that you wanted some private and some public in the state literal? – Dom Mar 31 '19 at 23:55
  • 1
    Make another object, like `publicSelf`, which contains the public properties, and is passed to `Object.assign` (probably also change the name of `self` to `privateSelf` to make things clear) – CertainPerformance Mar 31 '19 at 23:56
  • Ahh i see, so in that case on other objects being assigned, you would use the 'this' keyword to address properties in the publicSelf object. – Dom Apr 01 '19 at 20:35
0

Just don't pass name into self on the first line of alligator. You can still use it inside the alligator function without assigning it to the returned object.

leftclickben
  • 4,564
  • 23
  • 24