2013-03-30 53 views
10

這可能已經被問過很多次了,我已經搜索過,但到目前爲止,我讀到的所有答案都不是我正在尋找的。對象文字或模塊化Javascript設計模式

我正在使用中等DOM元素顯示/隱藏,一些AJAX調用和其他可能的網站。所以,我將有兩個主要的腳本文件(HTML5樣板標準)

plugins.js // third party plugins here 
site.js // all my site specific code here 

以前我使用對象文本的設計模式,所以我site.js是這樣的:

var site = { 
    version: '0.1', 
    init: function() { 
    site.registerEvents(); 
    }, 
    registerEvents: function() { 
    $('.back-to-top').on('click', site.scrollToTop); 
    }, 
    scrollToTop: function() { 
    $('body').animate({scrollTop: 0}, 400); 
    } 
}; 

$(function() { 
    site.init(); 
}); 

到目前爲止好,可讀性好,所有方法都是公開的(我有點像這樣,因爲如果需要,我可以通過Chrome開發工具直接測試它們)。不過,我打算去耦一些網站的功能將更加模塊化的風格,所以我想有這樣的事情下面的代碼以上(或在單獨的文件):

site.auth = { 
    init: function() { 
    site.auth.doms.loginButton.on('click', site.auth.events.onLoginButtonClicked); 
    }, 
    doms: { 
    loginButton: $('.login'), 
    registerButton: $('.register') 
    }, 
    events: { 
    onLoginButtonClicked: function() { 
    } 
    }, 
    fbLogin: function() { 
    } 
}; 

site.dashboard = { 
}; 

site.quiz = { 
}; 

// more modules 

正如你所看到的,這是非常可讀。然而,有一個明顯的缺點,那就是我必須編寫代碼,如site.auth.doms.loginButtonsite.auth.events.onLoginButtonClicked。突然間,它變得很難閱讀,而且只會越長,功能越複雜。然後我嘗試了模塊化的模式:

var site = (function() { 
    function init() { 
    $('.back-to-top').on('click', scrollToTop); 
    site.auth.init(); 
    } 

    function scrollToTop() { 
    $('body').animate({scrollTop: 0}, 400); 
    } 

    return { 
    init: init 
    } 
})(); 

site.auth = (function() { 
    var doms = { 
    loginButton: $('.login'), 
    registerButton: $('.register') 
    }; 

    function init() { 
    doms.loginButton.on('click', onLoginButtonClicked); 
    } 

    function onLoginButtonClicked() { 

    } 

    return { 
    init: init 
    } 
})(); 

// more modules 

正如你所看到的,那些長的名字都消失了,但我想我必須初始化所有其它模塊在site.init()函數來構建它們呢?然後我必須記得返回需要被其他模塊訪問的函數。他們兩個都沒問題我想雖然有點麻煩,但總體而言,我是否採用了模塊化模式更好的工作流程?

+0

'this.doms.loginButton.on('click',this.events.onLoginButtonClicked);'? – Bergi

+0

這可能會奏效,不敢相信我沒有嘗試過。但與模塊化模式相比,寫入仍然很長。 – Henson

回答

15

正確答案在這裏當然是:「取決於」。

如果您對所有數據和所有方法都完全沒問題,那麼對於您網站的每個部分都是100%公開的,那麼只需使用單個文字(或多個文字)以及嵌套對象(如果需要)假設你可以防止它變成一個巨大的代碼球。

如果您想要任何類型的持久性的私有狀態(即:每次運行某個函數時都不會重置),那麼揭示模塊非常棒。

這就是說:
這不是揭示模塊的要求對你有一個.init方法,在所有。
如果您的模塊可以自成一體,那麼只需將注意力集中在導出您想要公開的內容上。爲此,當我在編寫團隊可能會看到的代碼時,我發現自己創建了一個public_interface對象並將其返回(您返回的匿名對象的指定版本)。

這樣做的好處是最小的,除了增加理解,任何需要公開的內容都需要添加到界面上。

的方式,您目前正在使用它:

var module = (function() { /* ... */ return {}; }()); 

module.submodule = (function() { /*...*/ return {}; }()); 

沒有更好的或者比文字更糟糕,因爲你可以很容易地做到這一點:

var module = { 
    a : "", 
    method : function() {}, 
    meta : { } 
}; 

module.submodule = { 
    a : "", 
    method : function() {}, 
    meta : { } 
}; 

直到你碰到了什麼東西,其沒有按爲你工作,滿足你的需求。

就個人而言,我通常會構建任何僅數據對象的文字:配置對象,從其他連接進來的對象,等...

任何灰塵,簡單對象需要也許一個或兩個方法,並且可以通過嵌套一個或兩個深度來構建,我也可以從字面上構建(只要它不需要初始化)。

// ex: 
var rectangle = { 
    width : 12, 
    height : 24, 
    area : 0, 
    perimeter : 0, 
    init_area : function() { this.area = this.width * this.height; return this; }, // buh... 
    init_perimeter : function() { this.perimeter = (this.width * 2) + (this.height * 2); return this; } // double-buh... 
}.init_area().init_perimeter(); 

如果我需要其中幾個,也許我會做一個構造函數。
但如果我只需要獨特的這樣一個東西,是不是救我有些頭疼,只是做這樣的事情:

var rectangle = (function (width, height) { 
    var public_interface = { 
     width : width, 
     height : height, 
     area : width * height, 
     perimeter : (2 * width) + (2 * height) 
    }; 
    return public_interface; 
}(12, 24)); 

如果需要更多的先進的計算,我可以保持任何私人的額外變量,並從內部對其進行處理。
如果我需要在對象中有敏感數據,並且需要處理這些數據,那麼我可以使用調用這些私有函數的公共函數,並返回結果,而不是提供訪問權限。另外,如果我重構我的代碼,並決定在某個時刻重命名rectangle,那麼嵌套3或更深的任何函數也將被修改,這些函數指的是rectangle
同樣,如果你正在構建你的方法,使他們不需要直接問這進一步達比this任何對象,那麼你不會有這樣的問題...

...但如果你有一個看起來像一個接口:

MyApp.myServices.webService.send(); 

而且它希望找到:

MyApp.appData.user.tokens.latest; // where personally, I might leave tokens in a closure 

如果你改變你的應用程序數據模塊的結構,你將有各種錯誤的你的webService模塊,直到找到所有舊格式的引用,並將其全部重命名。

+0

因此,在任何情況下,除了隱私和個人偏好之外,使用Object Literal和Revealing Modular之間沒有真正的優點/缺點? – Henson

+1

@henson在對象文字中,內部引用依賴於其他屬性,這些屬性必須在事實之後進行計算,或者在對象的方法中創建閉包,這需要屬性在您處於預存狀態時預先存在試圖創造這個功能......這一切都歸結爲複雜性。如果你可以管理你的所有對象結構,這樣所有的大對象都只是非常原始的數據,那麼對象文字就沒有問題。如果你需要關閉,或者需要根據預先存在的對象成員進行預先計算,那麼文字就是一團糟的{。} .init() – Norguard