stampit-org / stampit

OOP is better with stamps: Composable object factories.
https://stampit.js.org
MIT License
3.02k stars 102 forks source link

Arrow notation in init function #303

Closed giper45 closed 7 years ago

giper45 commented 7 years ago

Thanks for this wonderful library ! Just I little question (for curiosity), why when I use arrow function notation in init function it gives empty object on instantiation ? I.e with normal notation:

// Some privileged methods with some private data.
const Availability = stampit().init(function() {
  var isOpen = false; // private

  this.open = function open() {
    isOpen = true;
    return this;
  };  
  this.close = function close() {
    isOpen = false;
    return this;
  };  
  this.isOpen = function isOpenMethod() {
    return isOpen;
  }
});
console.log(Availability())

>> { open: [Function: open],
  close: [Function: close],
  isOpen: [Function: isOpenMethod] }

while the arrow notation gives this :

// Some privileged methods with some private data.
const Availability2 = stampit().init(() => {
  var isOpen = false; // private

  this.open = function open() {
    isOpen = true;
    return this;
  };  
  this.close = function close() {
    isOpen = false;
    return this;
  };  
  this.isOpen = function isOpenMethod() {
    return isOpen;
  }
});
console.log(Availability2()) 

>> {}

Thanks !

amelon commented 7 years ago

arrow functions are some kind special. They are bound to their outside context and cannot be bound to your stamp instance.

Don't use fat arrow function with init method.

koresar commented 7 years ago

Thanks @amelon ! I'll put some code examples for @giper45

const outerObject = {
  name: "outerObject",

  f1: function() { // <---------- regular function
    console.log(this); 

    const innerObject = {
      name: "innerObject",
      f2: () => { // <---------- arrow function
        console.log(this);
      }
    };

    innerObject.f2();
  }
};

outerObject.f1();

The code above will print:

{ name: 'outerObject', f1: [Function: f1] }
{ name: 'outerObject', f1: [Function: f1] }

It prints the same object! Why? Because arrow functions (f2) INHERIT the this context of the running function (f1).


There is a way to use arrow functions as initializers. Here it is:

const Availability2 = stampit().init((_, {instance}) => {

  instance.open = function open() { }; // See this `instance` variable?
  // ...
});

If any questions feel free to ask.

giper45 commented 7 years ago

Thanks very much for the explanation !!! I've learned something more about Javascript in general :) !