【问题标题】:Overriding methods using Javascript module pattern使用 Javascript 模块模式覆盖方法
【发布时间】:2012-09-06 16:22:34
【问题描述】:

我有一个浏览器插件,我已经维护了 5 年,我想分享一些 Firefox 和 Chrome 版本之间的通用代码。

我决定使用Javascript Module Pattern,但遇到了问题,例如,加载特定于浏览器的首选项、保存数据和其他与浏览器相关的内容。

我想做的是让共享代码引用虚拟的、可覆盖的方法,这些方法可以在派生的、特定于浏览器的子模块中实现。

以下是我目前在 Firebug 控制台中使用我引用的文章中的 Tight Augmentation 方法尝试过的一个快速示例:

var core = (function(core)
{
    // PRIVATE METHODS
    var over = function(){ return "core"; };

    var foo = function() {
        console.log(over());
    };

    // PUBLIC METHODS
    core.over = over;
    core.foo = foo;

    return core;
}(core = core || {}));


var ff_specific = (function(base)
{
    var old_over = base.over;

    base.over = function() { return "ff_specific"; };

    return base;
}(core));

core.foo();
ff_specific.foo();

不幸的是,对 foo() 的两个调用似乎都打印了“核心”,所以我认为我对某些东西有根本的误解。

基本上,我希望能够打电话:

get_preference(key)
set_preference(key, value)
load_data(key)
save_data(key, value)

并让每个浏览器做自己的事情。这可能吗?有没有更好的方法?

【问题讨论】:

    标签: javascript overriding virtual-functions


    【解决方案1】:

    在 javascript 中,函数具有“词法范围”。这意味着函数在定义它们时创建它们的环境 - 范围,而不是在它们执行时。这就是为什么你不能稍后替换“over”函数的原因:

    var over = function(){ return "core"; };
    
    var foo = function() {
        console.log(over());
    };
    //this closure over "over" function cannot be changed later
    

    此外,您“说”“over”应该是“core”的私有方法,而“ff_specific”应该以某种方式扩展“core”并更改它(在这种情况下,私有方法不应被设计覆盖)

    【讨论】:

      【解决方案2】:

      您永远不会在 ff_specific 代码中覆盖对 foo 的调用,它直接引用私有函数 over()(永远不会被覆盖),而不是函数 core.over()(会被覆盖)。

      根据您的用例解决它的方法是将对 over() 的调用更改为对 core.over() 的调用。

      也就是说,你这么多地重复使用事物的名称真的让自己感到困惑,imo。也许这只是示例代码。我也不相信您需要将核心传递给基本函数(仅传递给子函数)。

      【讨论】:

        【解决方案3】:

        感谢您的帮助。我忘记了在定义闭包后我无法重新分配闭包。我确实想出了一个解决方案。

        问题的一部分只是盲目地遵循文章中的示例代码,这意味着构建模块的匿名函数被立即调用(Paul 提到的名称的重用)。无法重新分配闭包,即使是我专门公开的闭包,这意味着我以后甚至无法将具有自己的方法的对象传递给它,然后检查它们。

        这就是我最终做的事情,而且看起来效果很好:

        var ff_prefs = (function(ff_prefs)
        {
            ff_prefs.foo = function() { return "ff_prefs browser specific"; };
        
            return ff_prefs;
        }({}));
        
        
        var chrome_prefs = (function(chrome_prefs)
        {
            chrome_prefs.foo = function() { return "chrome_prefs browser specific"; };
        
            return chrome_prefs;
        }({}));
        
        
        var test_module = function(extern)
        {
            var test_module = {};
        
            var talk = function() {
                if(extern.foo)
                {
                    console.log(extern.foo());
                }
                else
                {
                    console.log("No external function!");
                }
            };
        
            test_module.talk = talk;
        
            return test_module;
        };
        
        
        var test_module_ff = new test_module(ff_prefs);
        var test_module_chrome = new test_module(chrome_prefs);
        var test_module_none = new test_module({});
        
        test_module_ff.talk();
        test_module_chrome.talk();
        test_module_none.talk();
        

        之前,它自己运行,然后当扩展启动时,它会调用一个 init() 函数,它仍然可以这样做。它不再是一个匿名函数。

        【讨论】:

        • 不需要在 test_module 之前使用“new”关键字。您没有使用“test_module”作为“构造函数”,您只是返回一个对象
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-11
        • 2012-06-05
        • 2013-07-10
        • 2014-06-04
        • 1970-01-01
        • 2021-01-06
        • 1970-01-01
        相关资源
        最近更新 更多