我有一个浏览器插件,我已经维护了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)
并让每个浏览器都做自己的事情。这可能吗?有没有更好的方法呢?
答案 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()函数,它仍然可以执行。它不再是一个匿名函数。