使用构造函数的模块化模式揭秘

17

我有点难以确定最佳实现方式。

我想要一个模块,它具有一个构造函数,该函数接受一个参数并将其存储以供稍后在模块内使用。

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

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

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

在一些其他的文件中

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

//...

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

现在在someMethod上面,moduleA是未定义的,而this是全局窗口对象。 有人能解释一下我如何访问moduleA吗? 我不明白在构造函数之后this.moduleA = moduleA;发生了什么。如果我在这里使用了错误的模式或其他内容,请随时参与。


我更新了例子,使其更加清晰。 - Kyle Gobel
1
@Chase 唯一的原因是 moduleA 是全局变量,所以才能使小提琴起作用。 - jbabey
3个回答

10

您很接近了,但在定义someMethod时缺少一些重要内容。

编辑:如果您在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/


谢谢你的示例。在我的实际情况中,“this”运算符并不总是ModuleB对象(我不知道,可能是我设计得不好)。在这个实现中,有什么我可以改变来使它适用于那些情况吗?还是我最好改变实现ModuleB的区域。示例在这里http://jsfiddle.net/QKZxh/1/。 - Kyle Gobel
2
原型上的函数应该始终将 this 指向调用对象。 - jbabey

1

试试这个:

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();

1
他的原型分配是IIFE(一个对象)的返回,而不是函数。 - jbabey
是的,但是一旦您创建了ModuleB,它就包含一个“原型”。如果您覆盖整个对象,所有对ModuleA的引用都将丢失。 - Adrian Salazar
moduleA 是每个对象实例的属性,与原型无关。 - jbabey
进一步解释@jbabey所说的,当moduleA作为参数传递时,它成为给定对象的属性。因此,当作为参数传递时,javascript进程会将其视为ModuleA,例如:var ModuleB = function(moduleA) { var moduleA; this.moduleA = moduleA; }。 - Filling The Stack is What I DO

0
你需要使用call/apply来执行给定上下文的方法。
尝试这段代码(我已经修改了你的代码)
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);

谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接