[英]Javascript Module Pattern create multiple instances using Prototype
我想要實現的目標:使用javascript中的原型創建模塊,以便用戶可以使用不同的選項多次實例化模塊。
問題 :當使用var my_module3 = new module();
然后嘗試使用my_module3.init({ option: "value" });
設置選項my_module3.init({ option: "value" });
每次都不會更改對象,它只會更改一次。
測試:當使用console.log
我們可以看到它打印出具有相同選項的兩個對象,即使它們設置不同
Object {first: "Barry", second: "Larry", third: "Sam"}
Object {first: "Barry", second: "Larry", third: "Sam"}
這是我的jsFiddle完整代碼: http : //jsfiddle.net/11bLouc8/2/
var module = (function () {
// default options
var options = {
first: "test",
second: "test2",
third: "test3"
};
// take in useroptions and replace default options
var module = function(userOptions) {
if (userOptions != null && userOptions != undefined
&& userOptions != 'undefined') {
for (var opt in options) {
if (userOptions.hasOwnProperty(opt)) {
options[ opt ] = userOptions[ opt ];
}
}
}
};
//prototype
module.prototype = {
init: module,
options: options
};
return module;
})();
// create a new instance
var my_module3 = new module();
my_module3.init({
first: "Mike",
second: "Lisa",
third: "Mary"
});
// another instance
var my_module2 = new module();
my_module2.init({
first: "Barry",
second: "Larry",
third: "Sam"
});
函數本身的屬性就像static
類成員(函數的屬性,而不是它的實例)
function prototype
屬性在不同實例中是不同的:
function test(){};
test.prototype = {
constructor : test,
first : '',
second : '',
third : '',
init : function(f, s, t){
this.first = f;
this.second = s;
this.third = t;
return this;
},
formatToString : function(){
return 'first : ' + this.first + ', second : ' + this.second + ', third : ' + this.third;
}
}
var t1 = new test().init(1, 2, 3);
var t2 = new test().init(4, 5, 6);
console.log(t1.formatToString());//outputs "first : 1, second : 2, third : 3"
console.log(t2.formatToString());//outputs "first : 4, second : 5, third : 6"
您正在使用一個立即調用的函數表達式(IIFE),就像Module模式所說的那樣,但是對於這種情況, 您需要多次調用您的IIFE 。 這涉及給它一個名字,以便你可以再次解決它,所以從技術上來說它不再是IIFE,但它的工作原理與IIFE相同。 我要繼續打電話給它
當您調用函數時,JavaScript會為其中的變量和閉包創建一個上下文。只要IIFE之外的任何內容都引用其中的任何內容,該上下文就會存在。 這就是傳統模塊模式使用IIFE的原因:您可以在IIFE的上下文中隱藏私有數據和功能。
但是因為您只調用該函數一次,所以您的所有模塊實例共享相同的上下文。 您將模塊選項存儲在options
變量中,該變量是該共享上下文的一部分,而不是模塊的一部分,因此當您更新其中一個模塊中的選項時,它會更新所有模塊中的選項。 有時,這就是你想要的,但不是你的情況。
您要做的是為每個模塊創建一個新的上下文。 這意味着您需要攜帶IIFE並對其進行引用,以便您可以多次調用它:換句話說,它不再是匿名函數(或者甚至不一定是IIFE)。 但這都是可行的。 這是一個可能的解決方案:
var moduleContext = function () {
// default options
var options = {
first: "test",
second: "test2",
third: "test3"
};
// take in useroptions and replace default options
var module = function(userOptions) {
if (userOptions != null && userOptions != undefined
&& userOptions != 'undefined') {
for (var opt in options) {
if (userOptions.hasOwnProperty(opt)) {
options[ opt ] = userOptions[ opt ];
}
}
}
};
//prototype
module.prototype = {
init: module,
options: options
};
return module;
};
var my_module3 = new (moduleContext())();
my_module3.init({
first: "Mike",
second: "Lisa",
third: "Mary"
});
var my_module2 = new (moduleContext())();
my_module2.init({
first: "Barry",
second: "Larry",
third: "Sam"
});
console.log(my_module2.options, my_module3.options);
魔術發生在這兩個new (moduleContext())()
行中。 moduleContext()
函數和IIFE一樣,為模塊構造函數設置上下文,然后返回它。 然后new
運算符處理返回的函數,並在沒有參數的情況下調用它(最后一組parens)。 由於在moduleContext()
上需要它們的相同原因,需要圍繞調用moduleContext()
的額外問題:它們解決了JavaScript解析器中的一些歧義。
現在,您的兩個模塊在兩個不同的上下文中創建。 因此,您可以在任一模塊中設置“common”選項對象(就像您當前那樣),但只會影響該模塊上下文中的options對象。 另一個沒有被觸及,因此您可以單獨設置選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.