第18章 モジュール

モジュールとは?

JavaScriptのモジュールは、関連する関数、変数、クラスなどを一つのファイルにまとめたものです。モジュールを使用することで以下のような利点が得られます。

  1. 再利用性: モジュールは再利用可能なコードの単位となります。一度作成したモジュールを、異なるプロジェクトやアプリケーションで再利用することができます。
  2. 名前空間: 変数や関数などの名前が他のコードと衝突することを防ぐことができます。モジュール内で定義された変数や関数は、エクスポートされない限りそのモジュール内でのみ有効です。これにより、グローバルスコープの汚染を避けることができます。
  3. メンテナンス: コードをモジュールに分割することで、各モジュールが持つ役割や機能が明確になります。これにより、コードのメンテナンスやデバッグが容易になります。
  4. 遅延評価: ES6モジュールは、インポートされるまで評価(実行)されません。これにより、アプリケーションの起動時間を短縮することができます。


ES6モジュールの基本

export: 外部からアクセスできるようにするためのキーワード。

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

import: 他のモジュールで定義されている機能を利用するためのキーワード。

// app.js
import { add, subtract } from './math.js';

console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2


デフォルトエクスポートと名前付きエクスポート

デフォルトエクスポート: モジュールごとに1つだけ定義できるエクスポート。

// greeter.js
export default function greet(name) {
  return `Hello, ${name}!`;
}

名前付きエクスポート: 複数のエクスポートを1つのモジュールから行う。

// math.js
export const multiply = (a, b) => a * b;
export const divide = (a, b) => a / b;


エイリアスを使ったインポート

// module.js
export const foo = "bar";

import { foo as myFoo } from './module.js';
console.log(myFoo);  // "bar"を出力


全てのエクスポートをインポートする

// module.js
export const foo = "bar";

import * as myModule from './module.js';
console.log(myModule.foo);  // "bar"を出力


HTML上で読み込む

モジュールをHTML上で読み込む際には、<script>タグのtype属性をmoduleとして指定します。

<script type="module" src="./main.js"></script>


スコープとは?

スコープとは、変数や関数などの識別子が参照できる範囲のことを指します。JavaScriptには主に3つのスコープがあります。

  1. グローバルスコープ: スクリプトのどこからでも参照できるスコープです。変数はデフォルトでグローバルスコープに属します(ただし、letconstclassを使用して宣言された変数は除く)。
  2. 関数スコープ: functionキーワードを使用して宣言された関数内でのみ参照できるスコープです。varキーワードで宣言された変数は関数スコープになります。
  3. ブロックスコープ: {}(波括弧)で囲まれた部分、例えばif文やforループ内部のスコープです。letconstclassで宣言された変数はブロックスコープに属します。


モジュールとスコープ

モジュールが導入されると、モジュール自体が独自のスコープを持つようになりました。これは、モジュール内で宣言された変数や関数は、そのモジュール内でのみ参照できるということを意味します。外部からアクセスしたい場合、それらの変数や関数を明示的にエクスポートする必要があります。

// module.js
let privateVar = "私はモジュール内のみ参照可能です";
export let publicVar = "私はエクスポートされたので外部からも参照可能です";

上記の例では、privateVarはモジュール内部でのみアクセス可能で、publicVarはエクスポートされているので、このモジュールをインポートする他のモジュールからもアクセスできます。


注意点

  1. 非同期読み込み: <script type="module">はデフォルトでdefer属性が指定されているとみなされ、ドキュメントの解析が完了してから実行されます。
  2. CORS: モジュールスクリプトはCORS(Cross-Origin Resource Sharing)チェックに従います。異なるオリジンからモジュールを読み込む場合、適切なCORSヘッダが必要です。
  3. MIMEタイプ: サーバーから返されるモジュールスクリプトのMIMEタイプは、application/javascriptである必要があります。


練習問題1.

mathFunctions.jsというモジュールを作成し、その中に足し算と引き算を行う2つの関数を定義してください。

・それらの関数をエクスポートして、main.jsという別のファイルでインポートして利用してください。


練習問題2.

person.jsというモジュールを作成し、その中にPersonというクラスを定義してください。クラスには、名前と年齢を引数とするコンストラクタと、自己紹介を行うメソッドを追加してください。

・このクラスをデフォルトエクスポートし、main.jsでインポートして、新しいPersonオブジェクトを作成して自己紹介メソッドを実行してください。


練習問題3.

shapes.jsというモジュールを作成し、その中にSquareCircleの2つのクラスを定義してください。それぞれのクラスには、面積を計算するメソッドを実装してください。

main.jsshapes.jsから2つのクラスをインポートしますが、SquareクラスはMySquareというエイリアスでインポートしてください。そして、それぞれのクラスを使用して面積を計算してください。