aboutsummaryrefslogtreecommitdiff
path: root/files/ja/mozilla/javascript_code_modules/using/index.html
blob: d1e91166e739334f3cd0d3bbc421b4f9ac4d1285 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
---
title: JavaScript コードモジュールの利用
slug: Mozilla/JavaScript_code_modules/Using
tags:
  - Add-ons
  - Extensions
  - XPCOM
translation_of: Mozilla/JavaScript_code_modules/Using
---
<div>{{gecko_minversion_header("1.9")}}</div>

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

<h2 id="Creating_a_JavaScript_code_module" name="Creating_a_JavaScript_code_module">JavaScript コードモジュールの作成</h2>

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

<pre class="brush: js">var EXPORTED_SYMBOLS = ["foo", "bar"];

function foo() {
  return "foo";
}

var bar = {
  name : "bar",
  size : 3
};

var dummy = "dummy";
</pre>

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

<pre class="brush: js">Components.utils.import("resource://app/my_module.jsm");

alert(foo());         // "foo" と表示される
alert(bar.size + 3);  // "6" と表示される
alert(dummy);         // 'dummy' はモジュールからエクスポートされないため、"dummy is not defined" と表示される
</pre>

<div class="note">
<p><strong>Note: </strong>あなたがコードモジュールにテスト変更を加えたとき、実行する前にアプリケーションビルドID(例、バージョンなど) が変わっているかどうか確認してください。 otherwise, you may find yourself running the previous version of your module's code.</p>
</div>

<h3 id="code_moduleのURL">code moduleのURL</h3>

<p>上記のサンプルからわかる通り、コードモジュールをインポートするためにはURLが必要となります。(上の例ではURLは"resource://app/my_module.jsm"となっています)</p>

<p>Code modulesは<strong>chrome:</strong> ({{gecko_minversion_inline("2")}}), <strong>resource:</strong>, or <strong>file:</strong> URLのどれかを使用してのみロードすることができます。</p>

<ul>
 <li>If you're writing an extension for Firefox 4 and already have a <a href="https://developer.mozilla.org/en-US/docs/Chrome_Registration">chrome.manifest</a> with a <code>content</code> instruction in it, you can put the code module in your content folder and reference it like your other content files via <code>chrome://&lt;yourextension&gt;/content/&lt;yourmodule&gt;.jsm.</code></li>
 <li>If your extension or application needs to support Mozilla 1.9.x (Firefox 3.x), you should register a new resource URL. Details on doing this are in the <a href="https://developer.mozilla.org/ja/docs/Mozilla/JavaScript_code_modules/Using$edit#Extending_resource.3A_URLs">"Extending resource: URLs" section</a> below.</li>
</ul>

<h3 id="Sharing_objects_using_code_modules">Sharing objects using code modules</h3>

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

<p>スコープ 1:</p>

<pre class="brush: js">Components.utils.import("resource://app/my_module.jsm");

alert(bar.size + 3);  // "6" と表示される

bar.size = 10;
</pre>

<p>スコープ 2:</p>

<pre class="brush: js">Components.utils.import("resource://app/my_module.jsm");

alert(foo());         // "foo" と表示される
alert(bar.size + 3);  // "13" と表示される
</pre>

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

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

<p>スコープ 1:</p>

<pre class="brush: js">Components.utils.import("resource://app/my_module.jsm");

bar = "foo";
alert(bar);         // "foo" と表示される
</pre>

<p>スコープ 2:</p>

<pre class="brush: js">Components.utils.import("resource://app/my_module.jsm");

alert(bar);         // "[object Object]" と表示される
</pre>

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

<p>{{h2_gecko_minversion("Unloading code modules", "7.0")}}</p>

<p><code><a href="https://developer.mozilla.org/en-US/docs/Components.utils.unload">Components.utils.unload()</a></code> allows you to unload a previously imported code module. Once this method has been called, references to the module will continue to work but any subsequent import of the module will reload it and give a new reference.</p>

<h3 id="Examples">Examples</h3>

<ul>
 <li>A template to download and edit is seen here on <a href="https://gist.github.com/Noitidart/9045387">GitHub - Gists - _template-BootstrapJSM.xpi</a></li>
</ul>

<h3 id="resource:_Protocol" name="resource:_Protocol">コードモジュールの配置</h3>

<div class="geckoVersionNote">
<div>{{gecko_callout_heading("2.0")}}</div>

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

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

<h4 id="Using_a_resource.3a_URL" name="Using_a_resource.3a_URL">resource: URL の使用</h4>

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

<pre>resource://&lt;alias&gt;/&lt;relative-path&gt;/&lt;file.js|jsm&gt;
</pre>

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

<ul>
 <li><code>app</code> - XUL アプリケーションのパスへのエイリアス。</li>
 <li><code>gre</code> - XUL ランタイムのパスへのエイリアス。</li>
</ul>

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

<p><code>&lt;alias&gt;</code> must be unique to your add-on, as the application and other extensions share the same namespace for all aliases.</p>

<h3 id="chrome.manifestを使う">chrome.manifestを使う</h3>

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

<pre>resource <em>aliasname</em> <em>uri/to/files/</em></pre>

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

<pre>resource foo modules/</pre>

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

<pre class="brush: js">Components.utils.import("<a rel="freelink">resource://foo/bar.js</a>");
</pre>

<h3 id="プログラムによるエイリアスの追加">プログラムによるエイリアスの追加</h3>

<p>{{interface("nsILocalFile")}} として表せるパスへの独自のエイリアスをプログラムによって追加することもできます。以下に例を示します。</p>

<pre class="brush: js">var ioService = Components.classes["@<a class="linkification-ext" href="http://mozilla.org/network/io-service;1">mozilla.org/network/io-service;1</a>"]
                          .getService(Components.interfaces.nsIIOService);
var resProt = ioService.getProtocolHandler("resource")
                       .QueryInterface(Components.interfaces.nsIResProtocolHandler);

var aliasFile = Components.classes["@<a class="linkification-ext" href="http://mozilla.org/file/local;1">mozilla.org/file/local;1</a>"]
                          .createInstance(Components.interfaces.nsILocalFile);
aliasFile.initWithPath("/some/absolute/path");

var aliasURI = ioService.newFileURI(aliasFile);
resProt.setSubstitution("myalias", aliasURI);

// コードモジュールはサブフォルダではなくエイリアスフォルダ直下にあるとする
</pre>

<h2 id="Notes">Notes</h2>

<h3 id="Custom_modules_and_XPCOM_components" name="Custom_modules_and_XPCOM_components">カスタムモジュールと XPCOM コンポーネント</h3>

<p>{{Gecko("2.0")}} より前のバージョンでは、JavaScript XPCOM コンポーネントは、chrome が登録される前に読み込まれることに注意してください。これは、コンポーネントソース内のトップレベルにおいて独自の resource URL で <code><a href="/ja/docs/Components.utils.import">Components.utils.import()</a></code> が使用できないことを意味します。可能な解決策は、<a href="/ja/docs/Components.utils.import"><code>Components.utils.import()</code></a> の呼び出しを XPCOM コンポーネントのコンストラクタ内に移動することです (<a href="http://groups.google.com/group/mozilla.dev.apps.firefox/browse_thread/thread/e178d41afa2ccc87?hl=en#">このことについての議論</a>を参照してください)。</p>

<h3 id="Packaging_notes">Packaging notes</h3>

<p>It's important to note that you should not typically put your JavaScript code modules in a JAR file in your add-on. Firefox 3.6 doesn't support them at all, and there's only one case in which it's remotely useful: a Firefox 4-only add-on which must be installed unpacked. Otherwise placing code modules in a JAR file breaks compatibility unnecessarily.</p>

<h2 id="Importing_CommonJS_modules">Importing CommonJS modules</h2>

<p>The JavaScript code modules described here are not the same thing as <a href="http://www.commonjs.org/specs/modules/1.0/">CommonJS modules</a>, but you can import CommonJS modules into any scope where you can use <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.import">Components.utils.import</a>. Just call the following:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">const</span> <span class="punctuation token">{</span> require <span class="punctuation token">}</span> <span class="operator token">=</span> Cu<span class="punctuation token">.</span><span class="keyword token">import</span><span class="punctuation token">(</span><span class="string token">"resource://gre/modules/commonjs/toolkit/require.js"</span><span class="punctuation token">,</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">)</span></code></pre>

<p>This will import <code>require()</code> into your scope.</p>

<p>You can then use that to import CommonJS modules. You can import <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/SDK">Add-on SDK</a> modules in just the same way you could from an SDK add-on:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="comment token">// import the SDK's base64 module</span>

<span class="keyword token">var</span> base64 <span class="operator token">=</span> <span class="function token">require</span><span class="punctuation token">(</span><span class="string token">"sdk/base64"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
base64<span class="punctuation token">.</span><span class="function token">encode</span><span class="punctuation token">(</span><span class="string token">"hello"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// "aGVsbG8="</span></code></pre>

<p>You can import other CommonJS modules, too, as long as you know the path to them:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="comment token">// import my module</span>

<span class="keyword token">var</span> myModule <span class="operator token">=</span> <span class="function token">require</span><span class="punctuation token">(</span><span class="string token">"resource://path/to/my/module.js"</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>In this case, though, you might be better off <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/_loader">creating your own loader</a>, so you can specify the <code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/_loader#paths">paths</a></code> property yourself.</p>

<h2 id="関連項目">関連項目</h2>

<ul>
 <li><a href="/ja/docs/Mozilla/JavaScript_code_modules">JavaScript コードモジュール</a>のトピックのページ。</li>
 <li><a href="http://wiki.mozilla.org/Labs/JS_Modules">Mozilla Labs JS Modules</a> - このページは JS モジュールの一覧、加えて拡張機能開発者が利用できるコードのダウンロードリンクと文書を特集しています。</li>
</ul>