Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object.create, chaining and 'this'

Given the following program, console logs correctly - note the chained init function and return this:

const cat = {
  init(sound) {
    this.sound = sound;
    return this;
  },
  makeSound() {
    console.log(this.sound);
  }
};

const fluffy = Object.create(cat).init('meeeaaaauuu');
fluffy.makeSound();

My question: how and why is return this required for it to work? See error below with it removed:

const cat = {
  init(sound) {
    this.sound = sound;
    // return this
  },
  makeSound() {
    console.log(this.sound);
  }
};

const fluffy = Object.create(cat).init('meeeaaaahuuu');
fluffy.makeSound();

MDN states Object.create returns the new object, so chaining init() should work... Thinking it through... is it because the new object that's chained is still 'anonymous'?

Note that if init() gets its own line, all works as I would expect, without needing return this:

const fluffy = Object.create(cat);
fluffy.init('meeeaaaahuuu');
fluffy.makeSound();
like image 772
calipoop Avatar asked Jun 13 '17 03:06

calipoop


Video Answer


2 Answers

The reason this works:

const fluffy = Object.create(cat);
fluffy.init('meeeaaaahuuu');
fluffy.makeSound();

is because you're assigning fluffy the return value of Object.create. When you do const fluffy = Object.create(cat).init('meeeaaaahuuu');, you're calling init on the return value of Object.create, and assigning the return value of init to fluffy, which is undefined without a return statement.

like image 74
kyle Avatar answered Oct 17 '22 12:10

kyle


As @zerkms mentions, if init lacks a return statement, it will return undefined.

In the following line, fluffy is getting assigned the value returned by init

const fluffy = Object.create(cat).init('meeeaaaahuuu');

If init lacks a returns statement, fluffy will be assigned the value undefined

console.log(fluffy); // undefined

If init returns the object being assigned to cat, then fluffy will be assigned that value.

To demonstrate this another way, your chained assignment statement const fluffy = Object.create(cat).init('meow'); could have been written like this for the same result

let fluffy = Object.create(cat);
fluffy = init('meow');
like image 4
sfletche Avatar answered Oct 17 '22 12:10

sfletche