使用Javascript模块模式重写方法

使用Javascript模块模式重写方法,javascript,overriding,virtual-functions,Javascript,Overriding,Virtual Functions,我有一个已经维护了5年的浏览器插件,我想在Firefox和Chrome版本之间共享一些通用代码 我决定使用,但我遇到了一个问题,例如,加载特定于浏览器的首选项、保存数据和其他依赖于浏览器的内容 我想做的是让共享代码引用虚拟的、可重写的方法,这些方法可以在派生的、特定于浏览器的子模块中实现 下面是我到目前为止所得到的一个快速示例,我在Firebug控制台中使用了我引用的文章中的紧密增强方法: var core = (function(core) { // PRIVATE METHODS

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

我决定使用,但我遇到了一个问题,例如,加载特定于浏览器的首选项、保存数据和其他依赖于浏览器的内容

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

下面是我到目前为止所得到的一个快速示例,我在Firebug控制台中使用了我引用的文章中的紧密增强方法:

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()的两个调用似乎都打印了“core”,所以我认为我对某些东西有一个基本的误解

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

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

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

在特定于ff_的代码中,您从未重写对foo的调用,它直接引用私有函数over()(它从未被重写),而不是函数core.over()(它被重写)

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


也就是说,在我看来,你这么多地重复使用事物的名称真的让你自己很困惑。也许这只是示例代码。我也不认为需要将核心传递给基函数(仅传递给子函数)。

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”并对其进行更改(在这种情况下,私有方法不打算被设计覆盖)

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

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

不需要在测试模块之前使用“new”关键字。您没有将“test_module”用作“构造函数”,而是返回一个对象