使用Javascript模块模式覆盖方法

时间:2012-09-06 16:22:35

标签: javascript override virtual-method

我有一个浏览器插件,我已经维护了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)

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

3 个答案:

答案 0 :(得分:1)

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

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

那就是说,你真的很困惑,重复使用这些东西的名字,imo。也许那仅仅是示例代码。我也不相信你需要将核心传递给基本功能(仅限于孩子们)。

答案 1 :(得分: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 :(得分:0)

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

部分问题只是盲目地遵循文章中的示例代码,这意味着立即调用构建模块的匿名函数(重复使用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()函数,它仍然可以执行。它不再是一个匿名函数。