簡體   English   中英

Javascript Module Pattern使用Prototype創建多個實例

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM