[英]Why in Firefox Addon the imported objects can not access the importers' imported modules?
为了澄清起见,请考虑以下简化示例:
一个.js
Components.utils.import('resource://gre/modules/Services.jsm');
let obj = {
init: function() {
Components.utils.import('chrome://myaddon/modules/two.jsm', this);
}
// code here has access to Services.jsm
}
two.js
this.EXPORTED_SYMBOLS = ['abc'];
this.abc = {
// abc is imported into obj()
// however as part of obj (), abc{} does not have access to Services.jsm
}
我知道这是如何运作的,但问题是为什么?
结果是,例如,必须在每个模块中赋予Services.jsm
。
尽管Firefox缓存了模块,并且在性能上并没有多大区别,但我想知道是否可以避免重复导入?
就像已经提到过的@ felix-kling一样,这是由于模块级别的隔离,如果您考虑一下,这很有道理。 如果不是这样,则其他模块不仅可以看到Services
还可以看到abc
。
但是,还有另一个重要原因:由于JS代码模块一次启动并在之后缓存,因此,如果两次导入two.jsm
,一次是从已经导入Services.jsm
的模块中导入,一次是从另一个未导入的模块中导入,将会发生什么情况。 ? 现在, two.jsm
“看到” Services
将取决于首先导入了其他模块中的哪个! 这将是非常讨厌的。
在这种情况下,您对“将abc导入到obj()中”的评论是错误的。 您的代码实际上将abc
导入顶级范围。 Cu.import
将始终导入到顶级作用域,除非您明确指定要导入到的另一个作用域。
"abc" in this; // false
"abc" in obj; // false
obj.init();
"abc" in this; // true
"abc" in obj; // false!
如果要将two.jsm
导入obj
,则需要使用第二个参数调用Cu.import
。
let obj = {
init: function() {
Components.utils.import('chrome://myaddon/modules/two.jsm', this);
}
};
"abc" in this; // false
"abc" in obj; // false
obj.init();
"abc" in this; // false
"abc" in obj; // true
但这当然不会影响Services
的可见性。
我想如果Cu.import
只是自动导入您仍然要导入的某些模块(例如Services.jsm
和XPCOMUtils.jsm
,那将XPCOMUtils.jsm
。 但是,由于遗留原因和向后兼容的限制,这种情况不会而且很可能永远不会发生。 (例如,我的代码中断导致导入的const {Promise} = Cu.import(..., {});
因为ES6添加了默认的Promise
global ...;这种向后兼容的问题/约束)。
好吧,显而易见的是,不要将Cu.import
用于自己的东西,而要使用其他东西。 一堆附加组件,包括 当然,所有SDK插件都具有自己的CommonJS风格的require()
实现。
loader
文档。 我知道Erik在另一个非SDK Scriptish插件中创建了一个加载器。 Sandbox
编写自己的自定义加载器。 如我这样做,我extSDK
样板(在loader.jsm所有全局符号== loader.jsm::exports
将是可见的每一个require
D模块)。 但是这样做可能需要大量额外的工作,额外的知识以及将现有的JS代码模块移植到基于require()
的模块上的工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.