0

明確にするために、次の単純化された例を検討してください。

one.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 はモジュールをキャッシュし、パフォーマンスに大きな違いはありませんが、インポートの繰り返しを回避できるかどうかを知りたいですか?

4

1 に答える 1

2

@felix-kling が既に述べたように、これはモジュール レベルの分離によるものであり、考えてみると非常に理にかなっています。それ以外の場合はServices、他のモジュールだけでなく、abc.

ただし、別の重要な理由があります。JS コード モジュールは 1 回開始され、その後キャッシュされるため、2 回インポートするとどうなるでしょうか。1two.jsm回は既にインポートされたモジュールから、Services.jsmもう 1 回はインポートされていない別のモジュールからです 現在、two.jsm「見る」Servicesことは、他のどのモジュールが最初にインポートされたかに依存します! これは非常に厄介です。

その文脈では、「abc is import into obj()」に関するあなたのコメントは間違っています。コードは実際にabc最上位のスコープにインポートされます。Cu.importインポートする別のスコープを明示的に指定しない限り、常にトップレベルのスコープにインポートされます。

"abc" in this; // false
"abc" in obj; // false
obj.init();
"abc" in this; // true
"abc" in obj; // false!

にインポートtwo.jsmする場合は、2 番目の引数を指定し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など、とにかくインポートするいくつかのモジュールを自動インポートすると便利だと思います。しかし、レガシーの理由と下位互換性の制約により、これは発生せず、今後も発生しない可能性があります。(たとえば、ES6がデフォルトのグローバルを追加したため、インポートされたコードブレークがありました...;そのような後方互換性の問題/制約)。Services.jsmXPCOMUtils.jsmconst {Promise} = Cu.import(..., {});Promise

代替案?

当然のことCu.importですが、自分のものではなく、別のものを使用することです。アドオンの束。もちろん、すべての SDK アドオンには、独自の CommonJS スタイルのrequire()実装があります。

  • 必要に応じて、SDK を使用せずに、または SDK の選択した部分のみを使用して、SDK ローダーを実際に再利用できます。loaderドキュメントを参照してください。Erik がそれ以外の非 SDK Scriptishアドオンでローダーを作成することは知っています。
  • 添え字ローダーに基づいて、独自のカスタム ローダーを作成できますSandbox。たとえば、定型文でそうしましたextSDK(loader.jsm 内のすべてのグローバル シンボルは、== loader.jsm::exportsrequired モジュールに表示されます)。

require()ただし、これを行うには、既存の JS コード モジュールをベース モジュールに移植するために、かなりの追加作業、追加の知識、および労力が必要になる場合があります。

于 2014-07-14T18:11:53.220 に答える