使用JavaScript模块模式时应该在哪里放置私有方法?

时间:2012-07-31 03:51:34

标签: javascript

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

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的东西?当我发现这种情况时,我应该采取任何措施吗?

3 个答案:

答案 0 :(得分: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;
})();

答案 1 :(得分: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());

答案 2 :(得分: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可能是此模块的命名空间全局对象,但您可以轻松地传入空对象或深度嵌套的命名空间。