6

我一直在使用 Javascript Revealing Module 模式,我喜欢它在公共接口和内部之间提供的清晰分离。但是,我不断遇到一种情况,这让我想知道我的整体使用模式是否正确,或者我是否应该使用该模式的一些变体。

问题是,当传递给模块的 init 函数并私下存储以供内部使用时,也需要在 Knockout 绑定表达式或其他模块中公开公开。模块的返回语句会立即执行,稍后会调用 init 函数,通常会传递一些动态参数,例如在 Razor 视图中的脚本块中呈现的 Ajax URL 或原始 JSON。因为模块的 return 语句只返回私有变量的副本而不是引用,所以我在 init 函数中设置该私有变量不能更改已经返回的内容。

var productsModule = function() {

var urls;

var init = function(ajaxUrls) {
    urls = ajaxUrls;
};

return {
    init: init,
    urls: urls,
    getUrls: function() { return urls; }
};

}();

var customersModule = function() {

var doSomethingWithProductsModule = function() {
    alert(productsModule.urls); // undefined
    alert(productsModule.getUrls()); // object   
} ;       

return {
    doSomethingWithProductsModule: doSomethingWithProductsModule
};

}();

var urls = {
getProduct: '/Product/'
};

productsModule.init(urls);

customersModule.doSomethingWithProductsModule();

我的解决方法是在一个函数中包装诸如“urls”之类的对象,然后通过 productsModule.getUrls() 访问它们。然而,这变得非常混乱,特别是如果变量是一个 Knockout observable,它本身就是一个函数,因此为了评估它,我需要使用像 productsModule.getMyObservable()() 这样的双括号。

有没有更好的方法来使用至少接近揭示模块模式的东西来获取最新的内部值?

4

3 回答 3

2

基本类型按值传递,对象按引用传递;urls你可以利用这个,而不是覆盖productsModule你只是更新它。这样,在初始模块调用中返回的引用保持最新。我已经更新了您的代码以显示我的意思。

var productsModule = function() {

var urls = {};

var init = function(ajaxUrls) {
    // Merge properties into the original object instead; more robust approach
    // may be needed
    for ( name in ajaxUrls ) {
        if (ajaxUrls.hasOwnProperty(name)) {
            urls[name] = ajaxUrls[name];
        }
    }
};

return {
    init: init,
    urls: urls,
    getUrls: function() { return urls; }
};

}();

var customersModule = function() {

var doSomethingWithProductsModule = function() {
    alert(productsModule.urls); // undefined
    alert(productsModule.getUrls()); // object
} ;   

return {
    doSomethingWithProductsModule: doSomethingWithProductsModule
};

}();

var urls = {
    getProduct: '/Product/'
};

productsModule.init(urls);

customersModule.doSomethingWithProductsModule();
于 2012-10-26T03:26:02.720 回答
2

尽管我不完全喜欢必须遍历对象的所有可能级别以像这样合并它们的想法,但 El Yobo 的回答让我考虑将模块函数本身的结果作为局部变量,我可以更新其属性.

var productsModule = function() {

var urls;

var init = function(ajaxUrls) {
urls = ajaxUrls;
result.urls = urls;
};

var result = {
init: init,
urls: urls
};

return result;

}();


// Before init
alert(productsModule.urls); // undefined

var urls = {
getProduct: '/Product/'
};

productsModule.init(urls);

alert(productsModule.urls.getProduct); // /Product/
于 2012-10-26T07:19:05.287 回答
1

为什么不让 urls 成为可观察的属性?

看我的例子:

http://jsfiddle.net/Razaz/zkXYC/1/

var productsModule = function() {

    var urls=ko.observable();

    var init = function(ajaxUrls) {
        urls(ajaxUrls);
    };

    return {
        init: init,
        urls: urls,
        getUrls: function() { return urls(); }
    };

}();

var customersModule = function() {

    var doSomethingWithProductsModule = function() {
        alert(productsModule.urls()); // undefined
        alert(productsModule.getUrls()); // object   
    };       

    return {
        doSomethingWithProductsModule: doSomethingWithProductsModule
    };

}();

var urls = {
    getProduct: '/Product/'
};

productsModule.init(urls);

customersModule.doSomethingWithProductsModule();​

问候。

于 2012-10-26T10:22:34.450 回答