一、代碼必須分紅不一樣的功能模塊——服務和模塊,避免把全部的代碼都放在一個$( document ).ready()裏。
二、不要重複代碼。識別不一樣功能模塊裏面的相同代碼並提取出來用繼承的方法來避免重複。
三、儘管jquery是以DOM爲中心,但javascript不是所有關於DOM的,不是全部的功能塊須要或應該有一個DOM表示。
四、鬆耦合。代碼之間經過 custom event,pub/sub完成消息傳遞。javascript
代碼組織的第一步就是把代碼分紅不一樣的部分。php
優勢:解決消除匿名函數,以配置參數爲中心,更方便去重構和重用。好比對事件處理函數,定義爲_開頭的函數,隱含其爲工具函數或私有函數,一個簡單的實例:java
// An object literal var myFeature = { myProperty: "hello", myMethod: function() { console.log( myFeature.myProperty ); }, init: function( settings ) { myFeature.settings = settings; }, readSettings: function() { console.log( myFeature.settings ); } }; myFeature.myProperty === "hello"; // true myFeature.myMethod(); // "hello" myFeature.init({ foo: "bar" }); myFeature.readSettings(); // { foo: "bar" }
上面例子就是經過賦值給一個對象來進行封裝的,這個對象有幾個屬性和方法,全部的屬性和方法都是公共的。
如何將對象應用在Jquery編寫的程序中,一個典型的Jquery程序以下:jquery
// Clicking on a list item loads some content using the // list item's ID, and hides content in sibling list items $( document ).ready(function() { $( "#myFeature li" ).append( "<div>" ).click(function() { var item = $( this ); var div = item.find( "div" ); div.load( "foo.php?item=" + item.attr( "id" ), function() { div.show(); item.siblings().find( "div" ).hide(); }); }); });
針對上面的代碼,起碼能夠優化幾點:
將和功能無關的部分獨立,能夠把url做爲配置參數,最後鏈式操做也能夠優化。app
// Using an object literal for a jQuery feature var myFeature = { init: function( settings ) { myFeature.config = { items: $( "#myFeature li" ), container: $( "<div class='container'></div>" ), urlBase: "/foo.php?item=" }; // Allow overriding the default config $.extend( myFeature.config, settings ); myFeature.setup(); }, setup: function() { myFeature.config.items .each( myFeature.createContainer ) .click( myFeature.showItem ); }, createContainer: function() { var item = $( this ); var container = myFeature.config.container .clone() .appendTo( item ); item.data( "container", container ); }, buildUrl: function() { return myFeature.config.urlBase + myFeature.currentItem.attr( "id" ); }, showItem: function() { myFeature.currentItem = $( this ); myFeature.getContent( myFeature.showContent ); }, getContent: function( callback ) { var url = myFeature.buildUrl(); myFeature.currentItem.data( "container" ).load( url, callback ); }, showContent: function() { myFeature.currentItem.data( "container" ).show(); myFeature.hideContent(); }, hideContent: function() { myFeature.currentItem.siblings().each(function() { $( this ).data( "container" ).hide(); }); } }; $( document ).ready( myFeature.init );
改完以後,能夠看到:
一、咱們把功能分紅了很小的方法。之後若是咱們想改變內容的展現,它是明確的,改變它。在原代碼中,是很難作到的。
二、消除了匿名函數的使用。
三、將配置選項從代碼的主體中移動,並將它們放在中心位置。
四、消除了外鏈的約束,使得代碼更容易重構。ide
模塊模式克服了對象封裝的一些侷限性,爲變量和函數提供了隱私,同時公開了一個公共接口。函數
// The module pattern var feature = (function() { // Private variables and functions var privateThing = "secret"; var publicThing = "not secret"; var changePrivateThing = function() { privateThing = "super secret"; }; var sayPrivateThing = function() { console.log( privateThing ); changePrivateThing(); }; // Public API return { publicThing: publicThing, sayPrivateThing: sayPrivateThing }; })(); feature.publicThing; // "not secret" // Logs "secret" and changes the value of privateThing feature.sayPrivateThing();
在上面的例子中,咱們自我執行一個匿名函數,返回一個對象。在函數的內部,咱們定義了一些變量。由於變量被定義在函數的內部,除非咱們把它們放在返回對象中,不然咱們就沒法訪問它們。這意味着函數之外的任何代碼沒法訪問的變量privateThing或變量changePrivateThing。然而,sayprivatething能夠訪問並得到privatething和changeprivatething,由於都是在相同的範圍內定義爲sayprivatething。
這種模式是強大的,由於你能夠從變量名稱中收集,它能夠給你私人的變量和函數,同時暴露一個有限的API組成的返回的對象的屬性和方法。
下面是一個修訂版的前面的例子,展現瞭如何咱們可使用模塊的格局:工具
// Using the module pattern for a jQuery feature $( document ).ready(function() { var feature = (function() { var items = $( "#myFeature li" ); var container = $( "<div class='container'></div>" ); var currentItem = null; var urlBase = "/foo.php?item="; var createContainer = function() { var item = $( this ); var _container = container.clone().appendTo( item ); item.data( "container", _container ); }; var buildUrl = function() { return urlBase + currentItem.attr( "id" ); }; var showItem = function() { currentItem = $( this ); getContent( showContent ); }; var showItemByIndex = function( idx ) { $.proxy( showItem, items.get( idx ) ); }; var getContent = function( callback ) { currentItem.data( "container" ).load( buildUrl(), callback ); }; var showContent = function() { currentItem.data( "container" ).show(); hideContent(); }; var hideContent = function() { currentItem.siblings().each(function() { $( this ).data( "container" ).hide(); }); }; items.each( createContainer ).click( showItem ); return { showItemByIndex: showItemByIndex }; })(); feature.showItemByIndex( 0 ); });