4

我已经开始在我的一个项目中使用模块模式。据我了解,它是这样的:

var obj = (function(foo){
     //Some initialization logic up here.

     //Private methods
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     //Public methods
     return { 
         publicFoo: foo,
         publicBar: function(){
             return foo + privateBazz;
         }
     }
})();

这在纸上看起来相当不错,在实践中,似乎工作得相当好。顶部的初始化逻辑是直观的,然后是私有方法,然后是公共方法。

不过,我遇到了一个问题。我应该如何从 return 语句的范围之外和 obj 的函数声明范围内调用 publicFoo 或 publicBar?

我目前的解决方案是执行以下操作:

var obj = (function(foo){
     //Private methods declared early for use.
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     var privateBar = function(){
         return foo + privateBazz;
     };

     //Some initialization logic up here.
     var dependentOnBar = privateBar();

     //Public methods
     return { 
         publicFoo: foo,
         publicBar: privateBar
     }
})();

这行得通,但是突然间我的私有变量的声明被放置在我的对象私有属性声明之上。如果我试图让私有函数声明与第一次调用它们的代码一样接近,问题会变得更加严重,所以我只是在顶部声明了我需要的所有私有函数,然后再初始化属性。同样,这可行,但我习惯于让代码尽可能靠近执行点。所以,在顶部声明私有函数块对我来说真的很尴尬。有没有其他人有这种感觉,或者这是我只需要克服 JavaScript 的问题吗?当我看到这种情况发生时,我应该采取什么步骤吗?

4

3 回答 3

1

听起来你可以通过简单地不使用对象表示法来返回模块来解决这个问题,而是初始化它并随时构建它。这将是这样的:

var obj = (function(foo){
     var self = {};
     //Some initialization logic up here.

     //Private properties
     var foo = "only accessible within this scope";

     //Private methods
     var privateBazz = function(){
         return "I'm known only to this closure!";
     }();

     //Public Properties
     self.publicFoo = foo;

     //Public Methods
     self.publicBar = function(){
         return foo + privateBazz;
     };

     return self;
})();
于 2012-07-31T04:30:46.207 回答
1

这是我的解决方案:如果您在返回之前将所有内容声明为“私有”方法并公开您想要公开的内容,那么您可以从公共内部调用您的私人,反之亦然(在您的第一个示例中,您的私人不能打电话给公众,因为他们当时没有被宣布)

var obj = (function() {
    // All functions now have direct access to each other
    var privateFunc = function() {
        return "private "+publicFunc1();
    };

    var publicFunc1 = function() {
        return "public 1 ";
    };

    var publicFunc2 = function() {
        return "public 2 "+publicFunc1();
    };


    var publicFunc3 = function() {
        return "public 3 "+privateFunc();
    };

    // Return the object that is assigned to Module
    return {
        publicFunc1: publicFunc1,
        publicFunc3: publicFunc3,
        publicFunc2: publicFunc2
    };
}());

alert(obj.publicFunc3());
于 2012-07-31T06:41:37.900 回答
0

如果您模拟CommonJS Modules,您可以将属性分配给exports对象,并通过限定或非限定名称从 IIFE 范围内的其他地方访问它们。

(function (exports, undefined) {
    var priv1 = 42;
    exports.pubOne = function () {};
    var localAlias = function () {};
    localAlias(42);
    exports.pubTwo = localAlias;
})(window.App);

在这个例子中,Window.App可能是这个模块的命名空间全局对象,但你可以很容易地传入一个空对象或一些深度嵌套的命名空间。

于 2012-07-31T04:15:56.077 回答