3

I would like to ask whether the following code is one way to implement inheritance using the module pattern. I would be grateful for any advice.

var Parent = (function() {

    function construct(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    };

    return construct;
})();

var Child = (function() {

    function construct() {

    };

    construct.prototype = new Parent();

    return construct;
})();
Antonios
  • 211
  • 3
  • 8
  • 1
    [Check this](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript) for better understanding. – The Alpha Nov 17 '13 at 18:30
  • Yes thank you for the reply I have used this excellent resource. I have seen various implementations how to mix module pattern and constructors and was wondering whether my implementation is valid. However, since the module pattern and the constructor pattern cover somewhat different usages is there an advantage in combining them, apart from the value of having private variables and functions? – Antonios Nov 18 '13 at 16:13

2 Answers2

1

The 'module pattern' and inheritance are orthogonal. Any technique for doing inheritance should work fine as long as you have a way to get references to the Parent while defining the Child.

There are a number of ways of doing inheritance. I would tend to suggest using whatever is built in to whatever library you are must likely using, however if you wanted to do it manually, what you're doing with setting the prototype to a new instance of the parent is fairly bad. A simple and good formulation would be something like this (es5):

function Child() {
    Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype, {
    constructor: {value:Child, writable: true,enumerable: false,configurable: true}
});

As to the module pattern, I would suggest choosing either the AMD format and using a tool like RequireJS to help you define your modules, or possibly using the Node.js flavour of CommonJS and using browserify to build it for the browser. Defining every class inside a module wrapper is slightly better than not doing so (primarily because it lets you make private class level variables), but doesn't really get you some of the big benefits of modules - importing other modules using a require mechanism is nicer than grabbing them from globals, not defining them as globals will stop you from messing up the global scope too much and could avoid nasty clashes.

If you are going to continue doing the wrapping manually, consider naming the constructor functions by the name of the classes rather than 'construct', as it can be quite helpful for debugging.

kybernetikos
  • 8,281
  • 1
  • 46
  • 54
1

To put the constructor function and prototype in a IIFE causes a little overhead as you're creating closures for every function but you only do it for the object definition, not for every object created.

I prefer to not put the Object definition in an IIFE because I never use privates and set up inheritance directly after the function deceleration: Child.prototype=Object.create(Parent.prototype);. More info about prototype and constructor functions here.

The following code demonstrates IIFE with private shared members, for instance specific private members check out the link previously posted.

var Parent = (function() {
    var sharedPrivateVal = 22;
    var privateFn = function(me){
      console.log("Current instance is:",me);
      return("returned from 'private' method");
    }
    function construct(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    };
    //all functions here are privileged even though they never need
    //access to 'private' variables
    construct.prototype.someFn=function(){
      console.log("someFn in parent");
    };
    construct.prototype.privilegedFn=function(){
      console.log("Accessing shared 'private' varaible:",sharedPrivateVal);
    };
    construct.prototype.privilegedFn2=function(){
      console.log(privateFn(this));
    };
    return construct;
}());

var Child = (function(p) {
    var _super = p.prototype;
    function construct() {
      p.apply(arguments);//re use parent constructor code
    };

    construct.prototype = Object.create(_super);//polyfill Object.create for older browsers
    construct.prototype.someFn=function(){
      _super.someFn.apply(arguments);//calling parent functon
      console.log("someFn in child");
    };
    construct.prototype.privilegedFn2=function(){
      console.log("No access to 'privates' when overriding"
        ,typeof privateFn);//you could re declare the function here 
                           //but you'll be doing copy and paste inheritance
                           //maybe consider widening IIFE scope and have
                           //both Parent and Child in an one IIFE if you must
                           //use private methods
      _super.privilegedFn2.apply(this,arguments);//ok when calling parent
    };


    return construct;
}(Parent));

var c = new Child();
c.someFn()
c.privilegedFn();
c.privilegedFn2();
Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160