mozilla
Your Search Results

    JavaScript コードモジュールの利用

    JavaScript コードモジュールは、Gecko 1.9 で導入されたコンセプトであり、特権を持った異なるスコープ間でコードを共有するために用いられます。また、モジュールは、グローバルな JavaScript のシングルトンオブジェクトを生成するために用いることもできます (以前は JavaScript XPCOM オブジェクトを使う必要がありました)。 JavaScript コードモジュールは、登録されたパスに配置された純粋な JavaScript のコードです。 Components.utils.import() を使って、 XUL スクリプトや JavaScript XPCOM スクリプトのような特定の JavaScript のスコープへモジュールを読み込むことができます。

    JavaScript コードモジュールの作成

    とても単純な JavaScript モジュールの例を以下に示します。

    var EXPORTED_SYMBOLS = ["foo", "bar"];
    
    function foo() {
      return "foo";
    }
    
    var bar = {
      name : "bar",
      size : 3
    };
    
    var dummy = "dummy";
    

    モジュールが普通の JavaScript を使って、関数、オブジェクト、定数、その他あらゆる JavaScript の型のオブジェクトを生成していることに注目してください。また、モジュールは EXPORTED_SYMBOLS という名前の特別な Array を定義します。 EXPORTED_SYMBOLS 内で命名されたすべての JavaScript オブジェクトは、モジュールからエクスポートされてインポート先のスコープ内で使用可能となります。以下に例を示します。

    Components.utils.import("resource://app/my_module.jsm");
    
    alert(foo());         // "foo" と表示される
    alert(bar.size + 3);  // "6" と表示される
    alert(dummy);         // 'dummy' はモジュールからエクスポートされないため、"dummy is not defined" と表示される
    

    Components.utils.import() の動作の非常に重要な点は、モジュールが読み込まれた時点でキャッシュされ、次のインポート時には、新しいバージョンのモジュールを再び読み込むことなく、以前にキャッシュされたバージョンを使用するということです。これは、モジュールが複数回インポートされた時に共有されることを意味します。モジュールをインポートしたあらゆるスコープ内で、データ、オブジェクト、関数の変更が可能となります。例えば、単一のモジュールが異なる 2 つの JavaScript のスコープ内へインポートされた場合、一方のスコープでの変更は他方のスコープにも影響します。

    スコープ 1:

    Components.utils.import("resource://app/my_module.jsm");
    
    alert(bar.size + 3);  // "6" と表示される
    
    bar.size = 10;
    

    スコープ 2:

    Components.utils.import("resource://app/my_module.jsm");
    
    alert(foo());         // "foo" と表示される
    alert(bar.size + 3);  // "13" と表示される
    

    このような共有の動作によって、ウィンドウや XUL スクリプト、XPCOM コンポーネントをまたいでデータを共有できるシングルトンのオブジェクトを生成することが可能となります。

    註: モジュールをインポートしたスコープごとに、そのモジュールでエクスポートされたシンボルの by-value コピーを受け取ります。シンボルの値の変更は他のスコープに伝搬することはありません。

    スコープ 1:

    Components.utils.import("resource://app/my_module.jsm");
    
    bar = "foo";
    alert(bar);         // "foo" と表示される
    

    スコープ 2:

    Components.utils.import("resource://app/my_module.jsm");
    
    alert(bar);         // "[object Object]" と表示される
    

    by-value コピーの主な効果は単純型のグローバル変数がスコープを横断して共有されないことです。常にラッパークラスの中に変数を置いてラッパーをエクスポートします (上の例にある bar のように)。

    コードモジュールの配置

    Gecko 2.0 note
    (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Gecko 2.0 より前のバージョンでは、JavaScript コードモジュールは、file: または resource: URL のみを用いて読み込むことができました。 Gecko 2.0 では、chrome: URL からのモジュールの読み込みが追加されましたが、これらは JAR アーカイブ内に限られます。

    Components.utils.import() を使用する場合、コードモジュールは、ディスク上のファイルを指し示すために file: または chrome:, resource: URL を使用して読み込まれなければなりません。

    resource: URL の使用

    Gecko 2.0 より前のバージョンでは、コードモジュールを読み込む最も一般的な方法は resource: URL を使用することでした。 resource URL の基本的な構文は以下のようになります:

    resource://<alias>/<relative-path>/<file.js|jsm>
    

    <alias> は通常、アプリケーションや XUL ランタイムの相対的なファイルパスへのエイリアスです。 XUL ランタイムによって予め定義されたいくつかのエイリアスがあります:

    • app - XUL アプリケーションのパスへのエイリアス。
    • gre - XUL ランタイムのパスへのエイリアス。

    <relative-path> は複数の階層とすることも可能で、常に <alias> で定義されたパスに対する相対パスとなります。一般的な相対パスは "modules" であり、 XUL Runner や Firefox にて使用されています。コードモジュールは拡張子 .js や .jsm の単一の JavaScript ファイルです。

    拡張機能や XUL アプリケーションへ独自のエイリアスを追加する最も簡単な方法は、 chrome manifest 内の以下のような行によって登録することです:

    resource aliasname uri/to/files/

    例えば、拡張機能 foo の XPI ファイルがモジュール bar.js を含むトップレベルの modules/ ディレクトリを有する場合 (つまり、modules/ ディレクトリが chrome.manifestinstall.rdf の兄弟)、以下の命令によってそのディレクトリへのエイリアスを作ることができます:

    resource foo modules/

    (末尾のスラッシュを忘れないこと!) すると、以下の一文でモジュールを JavaScript コードへインポートできるようになります:

    Components.utils.import("resource://foo/bar.js");
    

    カスタムモジュールと XPCOM コンポーネント

    Gecko 2.0 より前のバージョンでは、JavaScript XPCOM コンポーネントは、chrome が登録される前に読み込まれることに注意してください。これは、コンポーネントソース内のトップレベルにおいて独自の resource URL で Components.utils.import() が使用できないことを意味します。可能な解決策は、Components.utils.import() の呼び出しを XPCOM コンポーネントのコンストラクタ内に移動することです (このことについての議論を参照してください)。

    プログラムによるエイリアスの追加

    nsILocalFile として表せるパスへの独自のエイリアスをプログラムによって追加することもできます。以下に例を示します。

    var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                              .getService(Components.interfaces.nsIIOService);
    var resProt = ioService.getProtocolHandler("resource")
                           .QueryInterface(Components.interfaces.nsIResProtocolHandler);
    
    var aliasFile = Components.classes["@mozilla.org/file/local;1"]
                              .createInstance(Components.interfaces.nsILocalFile);
    aliasFile.initWithPath("/some/absolute/path");
    
    var aliasURI = ioService.newFileURI(aliasFile);
    resProt.setSubstitution("myalias", aliasURI);
    
    // コードモジュールはサブフォルダではなくエイリアスフォルダ直下にあるとする
    

    関連項目

    ドキュメントのタグと貢献者

    Contributors to this page: hiiragi77, ethertank, Marsf
    最終更新者: ethertank,