モジュールスコープとは

ES Modules では、各モジュールファイルが独自のスコープを持ちます。これを「モジュールスコープ」と呼びます。従来のスクリプトとは異なり、変数がグローバルを汚染することがありません。

グローバルスコープとの違い

通常のスクリプトでは、トップレベルで宣言した変数はグローバルスコープに追加されます。

<!-- 通常のスクリプト -->
<script src="a.js"></script>
<script src="b.js"></script>
// a.js
var name = "Alice";
let count = 0;
// b.js
console.log(name);  // "Alice"(グローバルに見える)
console.log(count); // エラーまたは意図しない動作

モジュールスコープの動作

モジュールでは、各ファイルが独立したスコープを持ちます。

<!-- モジュールとして読み込み -->
<script type="module" src="a.js"></script>
<script type="module" src="b.js"></script>
// a.js
const name = "Alice";
let count = 0;
// name と count は a.js 内でのみ有効
// b.js
console.log(name);  // ReferenceError: name is not defined
console.log(count); // ReferenceError: count is not defined
通常のスクリプト

トップレベルの変数はグローバル(window)に追加される。名前の衝突が起きやすい。

ES Modules

各ファイルが独立したスコープを持つ。明示的に export/import しない限り、他のモジュールからアクセスできない。

エクスポートによる公開

他のモジュールで使いたい値は、明示的にエクスポートする必要があります。

// a.js
export const name = "Alice";
const secret = "hidden"; // エクスポートしないのでプライベート
// b.js
import { name } from './a.js';
console.log(name);   // "Alice"
console.log(secret); // エラー(アクセスできない)

this の違い

モジュールのトップレベルでは、thisundefined になります。

// 通常のスクリプト
console.log(this === window); // true

// モジュール
console.log(this); // undefined

グローバルへのアクセス

モジュール内からグローバルオブジェクトにアクセスしたい場合は、明示的に window(ブラウザ)や globalThis を使用します。

// モジュール内でグローバルを設定
globalThis.myApp = {
  version: "1.0.0"
};

// または
window.myApp = {
  version: "1.0.0"
};
globalThis

ES2020 で導入された、環境を問わずグローバルオブジェクトにアクセスできる標準的な方法です。

window

ブラウザ環境でのみ使用可能です。Node.js では使えません。

モジュールスコープの利点

名前の衝突を防げる
依存関係が明確になる
プライベートな変数を簡単に作れる
意図しないグローバル汚染を防げる
// module.js
// これらはモジュール外からはアクセスできない
const privateData = [];
let counter = 0;

function privateHelper() {
  // 内部的なヘルパー関数
}

// 公開したいものだけエクスポート
export function addItem(item) {
  privateData.push(item);
  counter++;
}

export function getCount() {
  return counter;
}

モジュールスコープにより、カプセル化が自然に実現され、保守性の高いコードを書くことができます。