Revealing Module Pattern with a constructor
Asked Answered
B

3

17

I'm having a bit of trouble figuring out the best way to implement this.

I want a module that has a constructor that takes in an argument that stores it for later use within the module.

var ModuleB = function(moduleA) {
    this.moduleA = moduleA;
}

ModuleB.prototype = function() {
    //private stuff/functions
    function someMethod() {
        moduleA.doSomething();
    }

    //public api
    return {
        someMethod : someMethod
    };
}();

In some other file

//ModuleA defined elsewhere
var moduleA = new ModuleA();

//...

var module = new ModuleB(moduleA);
module.someMethod();

Now above in someMethod, moduleA is undefined, and this, is the global window object. Can someone explain how I would get access to moduleA? I don't understand what happens to this.moduleA = moduleA; after the constructor. I'm not really a javascript developer so if I'm using the wrong pattern here or something, feel free to chime in.

Bucella answered 22/8, 2013 at 12:44 Comment(2)
I updated the example to make it more clearBucella
@Chase the only reason that fiddle works is because moduleA is global.Mechanism
M
10

You are very close, but you're missing something important in your definition of someMethod.

EDIT: is is easier to tell what works and what doesn't if you change the name of the module property in ModuleB:

var ModuleA = function() {}

ModuleA.prototype = (function () {
    return {
        someMethod: function () {
            return 'foo';
        }
    };
}());

var ModuleB = function(moduleA) {
    this.innerModule = moduleA;
}

ModuleB.prototype = (function () {
    return {
        doStuff: function () {
            return this.innerModule.someMethod();
        }
    };
}());

var moduleA = new ModuleA();

var moduleB = new ModuleB(moduleA);
console.log(moduleB.doStuff()); // prints "foo"

http://jsfiddle.net/mN8ae/1/

Mechanism answered 22/8, 2013 at 13:2 Comment(2)
thank you for your example. In my real world situation the 'this' operator is not always the ModuleB object (idk, probably poor design by me I guess). Is there something I could change in this implementation to get it to work for those cases? Or would I be better off changing the areas that implement ModuleB. Example Here jsfiddle.net/QKZxh/1Bucella
functions on the prototype should always have this point to the calling objectMechanism
K
1

Try this:

var ModuleB = function(moduleA) {
    this.moduleA = moduleA;
}

// Simplifying your code, what was missin is the "this" keyword accessing the moduleA
ModuleB.prototype.someMethod = function() {       
   this.moduleA.doSomething();
};


var module1 = new ModuleB({ 
    doSomething: function(){ 
         alert('i do something'); 
    } 
});

module1.someMethod();
Keelson answered 22/8, 2013 at 12:59 Comment(4)
His prototype assignment is the return of an IIFE (an object), not a function.Mechanism
Yes but, as soon as you created ModuleB it contains a "prototype". If you overwrite the entire object, all the magic reference to moduleA will get lostKeelson
moduleA is a property of each object instance, it has nothing to do with the prototype.Mechanism
To expand on @jbabey, moduleA becomes a property of a given object when it is passed as a parameter.So, the javascript process sees ModuleA when passed as a parameter like. var ModuleB = function(moduleA) { var moduleA; this.moduleA = moduleA; }Oology
O
0

You would need to use call/apply to execute the method for given context.

try this code (I have modified your code)

var ModuleB = function(moduleA) {
     this.moduleA = moduleA;
      };

 ModuleB.prototype = function() {
     //private stuff/functions
     function someMethod() {

         this.doSomething();
     }

     //public api
     return {
         someMethod : someMethod
     }; }();


 var ModuleA=function(){
     this.doSomething=function(){
      alert('moduleA Method');   
     }; };

 var modA=new ModuleA(); var modB=new ModuleB(modA);
 modB.someMethod.call(modA);

Thanks!

Ottavia answered 26/2, 2014 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.