0

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

我决定使用Javascript 模块模式,但我遇到了一个问题,例如,加载特定于浏览器的首选项、保存数据和其他与浏览器相关的东西。

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

这是我到目前为止所获得的一个快速示例,我在 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)

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

4

3 回答 3

1

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

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

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

于 2012-09-06T16:38:41.103 回答
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”并更改它(在这种情况下,私有方法不应被设计覆盖)

于 2012-09-06T16:40:24.127 回答
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() 函数,它仍然可以这样做。它不再是一个匿名函数。

于 2012-09-06T16:58:54.377 回答