从阅读示例来看,这似乎应该很容易。这是我的代码:
rhkTest = {
onPageLoad: function(event) {
var doc = event.originalTarget;
var wnd = doc.defaultView;
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://rhkoshi-extension/content/testfoo.js", wnd);
alert('typeof(wnd) = ' + typeof(wnd));
alert('typeof(wnd.window.rhk_test1) = ' + typeof(wnd.window.rhk_test1));
alert('typeof(wnd.window.rhk_test2) = ' + typeof(wnd.window.rhk_test2));
alert('typeof(wnd.window.rhk_test3) = ' + typeof(wnd.window.rhk_test3));
alert('typeof(wnd.rhk_test1) = ' + typeof(wnd.rhk_test1));
alert('typeof(wnd.rhk_test2) = ' + typeof(wnd.rhk_test2));
alert('typeof(wnd.rhk_test3) = ' + typeof(wnd.rhk_test3));
alert('typeof(rhk_test1) = ' + typeof(rhk_test1));
alert('typeof(rhk_test2) = ' + typeof(rhk_test2));
alert('typeof(rhk_test3) = ' + typeof(rhk_test3));
alert('typeof(this.rhk_test1) = ' + typeof(this.rhk_test1));
alert('typeof(this.rhk_test2) = ' + typeof(this.rhk_test2));
alert('typeof(this.rhk_test3) = ' + typeof(this.rhk_test3));
alert('typeof(window.rhk_test1) = ' + typeof(window.rhk_test1));
alert('typeof(window.rhk_test2) = ' + typeof(window.rhk_test2));
alert('typeof(window.rhk_test3) = ' + typeof(window.rhk_test3));
},
onLoad: function(event) {
var appcontent = document.getElementById("appcontent");
if (appcontent) {
appcontent.addEventListener("DOMContentLoaded", rhkTest.onPageLoad, true);
}
},
};
window.addEventListener("load", function(e) { rhkTest.onLoad(e); }, false);
testfoo.js包含:
window.rhk_test1 = 'testval1';
rhk_test2 = 'testval2';
var rhk_test3 = 'testval3';
window.alert('Running testfoo.js');
我收到警告“正在运行testfoo.js”,因此找到并执行该文件。我也得到一个警告,注意到wnd是一个“对象”(正如预期的那样 - 它在别处初始化)。但是,所有其他警报显示各种typeof()调用的“未定义”。当然,我不希望这些所有都有值,但我希望至少一个可以显示一些东西。
我的价值观发生了什么变化?他们不应该属于wnd的属性吗?
我在Windows 7上运行Firefox 19.0(如果重要的话)。
答案 0 :(得分:3)
实际上有点复杂,取决于wnd
是什么。您可以使用常规对象作为下标的范围:
var myScope = this;
var subscriptScope = {};
loader.loadSubScript("testfoo.js", subscriptScope);
然而,范围并非完全孤立。以下是testfoo.js
中代码的一些示例:
var foo = "bar; // Creates subscriptScope.foo
xyz = 1; // Creates myScope.xyz
function dummy() {} // Creates subscriptScope.dummy
var outer = myScope; // Assigns a value from outer scope
因此,虽然下标的变量和函数在其范围内定义,但它仍然可以访问加载它的脚本的范围 - 仍然会在外部范围中创建未声明的变量,并且将搜索外部范围的变量无法在下标范围内解决。
如果你真的想要隔离下标,那么你应该使用一个“适当的”全局对象,如窗口对象或沙箱:
var myScope = this;
var subscriptScope = new Components.utils.Sandbox("about:blank");
loader.loadSubScript("testfoo.js", subscriptScope);
现在testfoo.js
将无法再访问外部范围:
var foo = "bar; // Creates subscriptScope.foo
xyz = 1; // Creates subscriptScope.xyz
function dummy() {} // Creates subscriptScope.dummy
var outer = myScope; // Exception: myScope is not defined
请注意,window
变量没有什么特别之处 - 如果您希望下标具有该变量,则必须在范围对象中定义它,例如:
subscriptScope.window = subscriptScope;
范围对象本身可以在下标的顶层访问this
。
答案 1 :(得分:1)
注意:请参阅Wladimir Palant的答案以获得更全面的概述。
就我的例子而言,我实际上正确地使用了这个功能,或多或少有合理的期望。问题是由Firefox的XPCNativeWrapper功能引起的。
我仍然在努力理解细节,但简而言之,我的wnd
对象被包装在XPCNativeWrapper中,testfoo.js
被认为是一个“受保护”的脚本,这意味着我控件从testfoo.js
传回后,无法看到对象所做的任何更改。
解决方案是在将对象解包之前(或之后也是如此)将对象解包到下标中,如下所示:
var wnd = XPCNativeWrapper.unwrap(doc.defaultView);
一旦我这样做,testfoo.js
修改的变量/属性对父脚本可见。
我还不了解完整的基础设施,以了解这是否“安全”。毕竟,这是一种安全机制,旨在保护我的扩展程序免受浏览器页面上的恶意代码的侵害。
我也看到了将对象传递给下标定义的方法的一些问题(在我的例子中没有显示)。为此,我将提出一个单独的问题。
长话短说:解缠是我问题中提出的直接问题的一个(可能是“解决方案”)解决方案,但似乎并不能完全解决我遇到的困难,从根本上解决问题