0

When using the module pattern in ES5, calling this.methodName gives me the methodName in the return object. But in ES6 it's a little bit different now....

The old way (with ES5):

  var moduleOld = (function() {
    //private
    var privateArray = [1,2,3,4];

    return {
      getItemCount: function() {
        return privateArray.length;
      },

      getTotal: function() {
        return this.getItemCount();
      }
    };
  })();

  //output
  console.log(moduleOld.getTotal()); //4 <-- Now, I want the same results with ES6 syntax 

The new way (with ES6):

  let moduleES6 = (()=> {
    //private
    let privateArray = [1,2,3,4];

    return {
      getItemCount: ()=> {
        return privateArray.length;
      },

      getTotal: ()=> {
        return this.getItemCount();
      }
    };
  })();

  //output
  console.log("es6 ", moduleES6.getTotal()); //Uncaught TypeError: this.getItemCount is not a function

There are ways around it...

  let moduleES6_2 = (()=> {
    //private
    let privateArray = [1,2,3,4];

    return {
      getItemCount: ()=> {
        return privateArray.length;
      },

      getTotal: ()=> {
        return moduleES6_2.getItemCount(); // I changed "this" to the module name, i.e. moduleES6_2
      }
    };
  })();

  //output
  console.log("es6 calling by module name: ", moduleES6_2.getTotal()); //works! But what if I change the module's name? Then I have to also change the function call in the getTotal function.

This way, changing the module's name shouldn't be much of an issue:

  let moduleES6_3 = (()=> {
    //private
    let privateArray = [1,2,3,4];
    function getItemCount() {
      return privateArray.length;
    }
    return {
      //getItemCount: getItemCount,
      getTotal: ()=> {
        return getItemCount(); // I am calling the private method. Not the public method!
      }
    };
  })();

  //output
  console.log("es6 by private method: ", moduleES6_3.getTotal()); //works! But I don't really use the method in the return object, but rather the private declared method.

How do I accesss a "public" function in the return object (module pattern) with ES6?

  let moduleES6 = (()=> {
    //private
    let privateArray = [1,2,3,4];
    function getItemCount() {
      return privateArray.length;
    }
    return {
      getItemCount: ()=> {
        return privateArray.length;
      },
      getTotal: ()=> {
        return this.getItemCount();//<-- how to access the public getItemCount method?
      }
    };
  })();
Cœur
  • 32,421
  • 21
  • 173
  • 232
thadeuszlay
  • 2,083
  • 4
  • 26
  • 57
  • 1
    In ES6 modules are the part of the language (`import`, `export` and friends) so there's no need for hacks like the "module pattern". – georg Jan 16 '17 at 00:09
  • @georg AFAIK import and export aren't supported natively by all Browsers. Just tried it with Chrome 53.0.2785.143 (64-bit) – thadeuszlay Jan 16 '17 at 00:58
  • _"The new way (with ES6)"_ That's not the new way, that's a different way. Arrow functions as methods rarely make sense. – a better oliver Jan 16 '17 at 07:53

1 Answers1

0

You can use the shorthand syntax for object methods like getItemCount():

let moduleES6 = (()=> {
  //private
  let privateArray = [1,2,3,4];

  return {
    getItemCount() {
      return privateArray.length;
    },

    getTotal() {
      return this.getItemCount();
    }
  };
})();

moduleES6.getTotal() //4
hackerrdave
  • 5,336
  • 1
  • 21
  • 27
  • Sorry that I can't double-check the following because I'm actually busy looking for something else: I suspect the problem is the use of arrow functions, which affect the 'this' pointer. So to fix it you either use the function() { ... } style of declaration, or you use hackerdave's approach. (I'd personally use hackerdave's approach.) – Mark Birbeck Jan 16 '17 at 00:08
  • @MarkBirbeck `getTotal() {` in object literal is a shortcut for `getTotal: function ....`. Which is needed to get proper `this`. The answer is correct, although ES6 module approach is preferable. – Estus Flask Jan 16 '17 at 00:57