2

我正在使用 javascript 模块模式,并且到目前为止:

var APP;
if(APP == undefined) {
  APP = {};
}

APP = (function() {
    var userId = -1;
    var privateVar = '';

    var _init = function($userId) {
       userId = $userId;
    };
    var _publicMethod = function($id){
        privateVar = id;
    };
    return {
        init = function($userId) {
             _init($userId);
         },
        publicMethod = function($id) {
           _publicMethod($id);
        }
    };
})();

然后我有一个通用的 utils 模块:

APP.utils = (function(){

})();

然后每个页面我都计划有一个模块,所以我不会在这些 DOM 元素不存在事件的页面上无缘无故地连接事件(按钮点击等):

APP.homePage = (function(){
     return {

     };
})();

所以每个模块都会有一个 init() 方法,我将在页面上调用它来运行必须运行的东西(例如连接事件,设置变量,比如 userId 等):

$(document).ready(function() {
   APP.init(<%= user.id %>);
   APP.homePage.init('abc');
});

所以现在如果文件太大,我也可以将它们分成单独的文件。

  1. 如果一个模块需要调用另一个模块怎么办,我想唯一可行的方法是通过公共 api 做到这一点,对吧?例如,如果 homePage 需要 userId,我应该在 homePage#init 方法中传递它吗?

  2. 我的编码风格如何,任何不被认为是最佳实践的明显风格?

  3. 对此方法有何评论?总的来说好吗?
4

2 回答 2

3

如果一个模块需要调用另一个模块怎么办,我想唯一可行的方法是通过公共 api 做到这一点,对吧?

是的

例如,如果 homePage 需要 userId,我应该在 homePage#init 方法中传递它吗?

不,我不会userId在所有模块中重复代码,而是在默认模块中为其提供公共 getter。

关于编码的任何评论

这段代码

var APP;
if(APP == undefined) {
  APP = {};
}

APP = ...

是很没用的。您不需要在这里检查对象是否存在,因为无论如何您都会覆盖它。这也意味着这段代码必须是第一个执行的。如果你想让模块独立于加载顺序,你需要使用类似的东西

var APP = (function(a) {
    var private_vars; // ...
    a.init = ...
    a.publicMethod = ... // add them to the object instead of creating new one
    a.getPrivate = function() {
        return private_vars;
    };
    return a;
})(APP || {}); // create one iff not already existing

// other file:
var APP = APP || {};
APP.utils = ... // add object to namespace

编码

var _publicMethod = function($id){
    privateVar = id;
};

看起来有点奇怪。首先,下划线通常表示对象的半私有(公共但不可使用)属性,不应用于变量名。这不是这里的情况,因为该函数将作为APP. 如果需要,请在此处使用下划线。其次,这里不需要使用函数表达式。代码在模块的本地范围内,使用函数声明既可以使其在该范围内的任何地方都可用,也可以命名函数。你应该使用

function publicMethod($id) {
    privateVar = id;
}
a.publicMethod = publicMethod;
于 2012-06-26T23:52:54.500 回答
1

在我看来,模块模式是组织代码的一种非常好的方式。要回答您的问题:

1)是的,您的模块只能访问已在它们返回的对象中公开的其他模块的方法和属性。

2)我认为你的编码风格看起来很不错。我会做出这些改变:

APP = (function() {
    var _userId = -1;
    var _privateVar = '';

    var init = function($userId) {
       _userId = $userId;
    };
    var publicMethod = function($id){
        _privateVar = id;
    };
    return {
        init : init,
        publicMethod : _publicMethod
    };
})();

首先,下划线通常表示“私有”属性或方法。其次,您可以取消返回对象中的额外功能,直接指向您关心的方法或属性。这通常被称为“显示模块模式”,因为即使是公共方法也没有在返回的对象中定义——它们只是被引用。

3)这种方法绝对是封装代码的好方法。您可以从私有方法和特权方法中受益,并且通常会得到更好的 API,因为您只公开需要公开的内容。

做得好。

于 2012-06-26T23:28:07.557 回答