こんにちは!フロントエンドの現場を渡り歩いてきたチーフアーキテクトの私です。
JavaScriptの勉強を進めていると、「あれ?これってどういう意味だっけ……?」と足が止まってしまう瞬間、ありますよね。特に「型」の話や「モジュール」の話が出てくると、途端に難解な暗号のように見えてしまって、そっとブラウザを閉じたくなる気持ち、痛いほどよく分かります。
でも、大丈夫ですよ。どんなにすごいエンジニアも、最初はみんな同じところでつまずいてきました。
今回は、JavaScriptの世界でモジュール(部品)を作るときに、そのモジュール全体の設計図をスマートに教え込んでくれる魔法の呪文、`@module` と `@exports` について、身近な例えを交えながら優しく紐解いていきましょう!
—
そもそも「モジュール」ってなんだろう?
いきなり難しい言葉が出てきましたが、難しく考える必要はありません。モジュールとは、いわば「お弁当の中の小さなおかずカップ」のようなものです。
大きなお弁当箱(アプリケーション)の中に、「唐揚げ」のカップ、「卵焼き」のカップ、「ブロッコリー」のカップ……と、役割ごとに綺麗に料理が仕切られていますよね。JavaScriptでも同じように、機能ごとにコードを小さく切り分けて部品化します。これが「モジュール」です。
そして、他のファイルでもその唐揚げを使えるように「はい、どうぞ!」と外の世界に持ち出せるようにする仕組みを、私たちは普段から使っています。
型の設計図(JSDoc)との出会い
「JavaScriptは型が自由奔放すぎて、どんなデータが入ってくるか分からなくなりがち……」
そんな現場のエンジニアたちの叫びを救うためにあるのが、コメントとして書く「JSDoc(ジェイエスドック)」という仕組みです。
コードの動きはそのままで、「この部品にはこういうデータを入れてね」「こういうデータが返ってくるよ」という説明書を、人間にもエディタ(VS Codeなど)にも分かりやすく教えてあげることができます。
その説明書の中で、「このファイル(モジュール)全体は、こういう仕様ですよ!」と宣言するときに使うのが、今回主役の `@module` と `@exports` なんです。
—
`@module` と `@exports` のコンビネーションを見てみよう
百聞は一見に如かず。実際にコードを見てみましょう。
ここでは、みんな大好き「お買い物計算」をしてくれる便利な道具(モジュール)を例にしますね。
/
- @file お買い物の合計金額を計算する便利ツールが入ったファイルだよ
- @module shoppingTool
/
/
- お買い物の計算結果をまとめるオブジェクトの型定義
- @typedef {Object} CalculationResult
- @property {number} subtotal – 消費税抜きの小計
- @property {number} tax – 消費税額
- @property {number} total – 税込の合計金額
/
/
- 税込み・税抜きをサクッと計算してくれるオブジェクト
- @type {Object}
- @property {function(number, number): number} calcTax 消費税を計算する関数
- @property {function(number, number): CalculationResult} createSummary 領収書用の明細を作る関数
/
const shoppingTool = {
/
- 金額と税率から税額を計算するよ
- @param {number} price – 元の金額
- @param {number} [taxRate=0.1] – 税率(指定しなかったら10%になるよ)
- @returns {number} 計算された税額
/
calcTax(price, taxRate = 0.1) {
return Math.floor(price taxRate);
},
/
- 小計と税金を合わせて、綺麗な明細データを作って返すよ
- @param {number} price – 商品の金額
- @returns {CalculationResult} さっき定義した明細オブジェクト
/
createSummary(price) {
const tax = this.calcTax(price);
return {
subtotal: price,
tax: tax,
total: price + tax
};
}
};
/
- このモジュール全体として外の世界に送り出すのは、この shoppingTool だよ!
- @exports shoppingTool
/
export default shoppingTool;
なんだか英語と記号が並んでいてウッとなったかもしれませんが、一つひとつ分解すれば怖くありません。
1. `@module shoppingTool`
> 「このファイル自体が、`shoppingTool`という名前の一つのまとまったお弁当箱(モジュール)ですよ」とエディタに伝えています。
2. `@exports shoppingTool`
> 「このモジュールを他のファイルで読み込んだとき、最終的に主役として渡すのはこの `shoppingTool` という中身ですよ」と教えてあげています。
—
エディタが優しくサポートしてくれる魔法の瞬間
なぜ、わざわざこんな面倒くさそうなコメント(JSDoc)を書くのでしょうか?
それは、私たちがコードを書いている最中に、VS Codeなどのエディタがもの凄く優しくおせっかいを焼いてくれるようになるからです。
別のファイルで、先ほど作ったモジュールを読み込んでみましょう。
import myTool from ‘./shoppingTool.js’;
// ここでドット(.)を打った瞬間……!
// エディタが「あ、これ、『calcTax』っていう関数と、『createSummary』っていう関数があるやつだよね?」と
// ピタッと予測変換の候補を出して教えてくれます。
const summary = myTool.createSummary(1500);
console.log(summary.total); // 1650 って表示されるよ!
もし、あなたが間違えて `createSummary(“1500円”)` と文字(文字列)を入れようものなら、エディタが「ちょっと待って!ここは数字(number)を入れてって説明書に書いてあるよ!」と、優しく赤く波線を出して警告してくれます。
これこそが、型定義の最大のメリットです。うっかりミスを、実行する前に未然に防いでくれる最強の相棒になってくれるんです。
—
初学者のあなたが安心して使うためのコツ
TypeScriptという本格的な型付き言語をいきなり導入するのはハードルが高いですが、JavaScriptのままで動かせるこのJSDoc形式(`@module` や `@exports`)であれば、今日書いているそのコードにコメントを足すだけで、すぐにでも実践できます。
- 最初は完璧を目指さなくて大丈夫
最初からすべての関数に細かい型を書こうとすると挫折しちゃいます。「ここは何を受け取るんだっけ?」と迷いそうな重要な部品だけに、そっと書き添えることから始めてみてください。
- エディタの補完を味方につける
JSDocを書いておくと、未来の自分がコードを見返したときに「おっ、親切な自分!」と感動できます。チーム開発はもちろん、自分一人で進めるプロジェクトでも強力な助っ人になります。
モジュールや型定義という言葉に気後れする必要はまったくありません。あなたの書くコードを、より優しく、より安全にしてくれる「お守り」のようなものだと思って、少しずつ触れてみてくださいね。
あなたのフロントエンド開発の旅が、今日も楽しく素晴らしいものになりますように!

コメント