2016-03-07 170 views
1

我正試圖圍繞不同模塊模式的偏移量進行打包。我看到寫這些模塊和暴露他們的數據的不同方式。JavaScript模塊模式差異

我在期待有關優缺點的信息,這裏沒有描述的更好的模式以及它們中的每一個的用例。


A)對象文字包裝在自調用函數,發射了用init方法:(source)

(function() { 

var MyModule = { 
    settings: { 
    someProperty: 'value'; 
    } 

    init: function() { 
    someMethod(); 
    } 

    someMethod: function() { 
    // ... 
    } 
}; 

MyModule.init(); 
})(); 

This是的一個例子的簡單的 「鳴叫這種」 實用程序我建立。我是否正確使用此模式?到目前爲止,這是我唯一一個有實際寫作經驗的人。


B)模塊的名稱空間的自調用匿名函數:(source)

var MyModule = (function() { 
    var MyObj = {} 

    function privateMethod() { 
    // ... 
    } 

    MyObj.someProperty = 1; 
    MyObj.moduleMethod = function() { 
    // ... 
    }; 

    return MyObj; 
}()); 

是否有比以往的風格有什麼優勢/劣勢?另外,在這裏使用對象文字符號的含義是什麼,而不是示例中的點語法?對象文字看起來更簡潔,但我並沒有真正意識到每個用例的恰當用例。


C)模塊作爲命名空間自調用匿名功能,而只能通過一個return塊暴露期望的結果:(source)

var MyModule = (function() { 
    var myPrivateVar, myPrivateMethod; 

    myPrivateVar = 0; 

    myPrivateMethod = function(foo) { 
    console.log(foo); 
    }; 

    return { 
    myPublicVar: "foo", 

    myPublicFunction: function(bar) { 
     myPrivateVar++; 
     myPrivateMethod(bar); 
    } 
    }; 

})(); 

類似於先前的樣式,而是暴露的的整個對象及其所有屬性/方法,我們只是通過return聲明暴露特定的數據位。


d)模塊作爲包裹在自調用匿名功能的功能,具有嵌套函數作爲方法。該模塊通過窗口對象暴露,然後經由new關鍵字構造:(source)

(function(window, undefined) { 

    function MyModule() { 

    this.myMethod = function myMethod() { 
     // ... 
    }; 

    this.myOtherMethod = function myOtherMethod() { 
     // ... 
    }; 

    } 

    window.MyModule = MyModule; 

})(window); 

var myModule = new MyModule(); 
myModule.myMethod(); 
myModule.myOtherMethod(); 

我假設這圖案的強度是如果模塊是一個種類,其中多個實體可能需要的「模板」存在於應用程序中。任何一個好的用例的具體例子?

+1

你應該看看Addy Osmani的書Javascript Design Patterns。它爲初學者介紹了這個主題。你可以在這裏免費閱讀https://addyosmani.com/resources/essentialjsdesignpatterns/book/ – nick

+1

這是一個非常廣泛的問題... –

回答

2

所有這些使用相同的模式只是略有不同的方式。

A)對象文字包裝在一個自調用函數,與init方法發射了:

這是好的,如果你不打算讓任何人訪問的代碼塊。你甚至不需要有一個init函數。將代碼封裝在IIFE(立即調用的函數表達式)中可防止全局命名空間污染,並允許使用「私有」變量。在我看來,這只是一個好習慣,而不是一個模塊。

B)模塊的名稱空間的自調用匿名函數:

這是當他們談論模塊模式是什麼人的意思。它給你私有變量和函數,然後通過公共接口公開這些變量和函數。在你的例子中,該接口恰好被稱爲MyObj

C)模塊作爲命名空間自調用匿名功能,而只能通過一個return塊暴露期望的結果:

這實際上是完全一樣的東西一個。唯一的區別是,接口上的方法不能像在B中那樣直接引用接口本身。例如:

MyObj.methodA = function() { 
    return MyObj.methodB(); 
}; 

,因爲你必須引用它一個名稱,但只有當你希望公衆的方法來使用除返回的對象執行上下文的任何其他被稱爲有用將與之前的例子。即,setTimeout(MyModule.methodA)(將與全局上下文被調用,從而旨在this.methodB()是行不通的。

d)模塊作爲包裹在自調用匿名功能的功能,具有嵌套函數作爲方法。該模塊通過窗口對象暴露,然後通過new關鍵字構造:

與前2個相同的東西除了2個小差異。 window作爲參數傳遞是因爲歷史上,訪問局部變量比全局變量更快,因爲引擎不必爬上作用域鏈。然而,現在大多數JS引擎優化訪問window,因爲它是常見的並且是已知的對象。同樣,undefined作爲參數給出,沒有任何參數作爲參數傳遞。這可確保您擁有正確的undefined值。這背後的原因是,從技術上講,您可以在非嚴格模式下爲undefined指定任何值。這意味着某些第三方可能會寫入undefined = true;,並且突然所有undefined檢查都失敗。

另一個區別是,你正在返回一個函數,而不是一個對象。這背後的好處是,您可以擁有在每個對象實例中共享的私有變量以及每個實例的私有變量。示例:

var count = 0; 
function MyObject(id) { 
    var myID = id; 
    count++; 

    // Private ID 
    this.getID = function() { 
    return myID; 
    }; 

    // Number of instances that have been created 
    this.getCount = function() { 
    return count; 
    }; 
} 

這樣做的缺點是您沒有將方法附加到原型。這意味着JS引擎必須爲每個對象的單個實例創建一個全新的函數。如果它在原型上,所有實例將共享相同的函數,但不能有單獨的私有變量。

+1

強烈的解釋已經清除了很多細節我失蹤了 - 謝謝! –