はじめに
JavaScript
についてフワッとしている部分がよくあったので、簡単ですが今回はモジュールについて少し調べました。
モジュールがない場合のデメリット
まず、モジュールがない場合のデメリットを考えてみましょう。
このように、2つのscript
タグが存在し、greet
変数の定義とコンソールにgreet
変数を表示させるとします。
<body>
<script>
const greet = 'おはよう';
</script>
<script>
console.log(greet);
</script>
</body>
ここで押さえておきたいのがJavaScriptコードが他のScriptタグで囲まれたコードも参照できてしまうということです。
言い換えると、グローバルな名前空間(スコープ)になっておりどこからでもgreet変数が参照できるということです。
どこからでもgreet変数呼べるなら便利じゃん! って思いますよね?
例えばコードがどんどん多くなった場合を考えてみましょう。
例えばAさんがgreet
変数を定義し、100行目で1行目に指定したgreet
変数を使うと問題なくおはようが表示されます。
<body>
<!-- 1行目 -->
<script>
const greet = 'おはよう';
</script>
<!-- 100行目 -->
<script>
console.log(greet);
</script>
</body>
一方で、Bさんが200行目付近で1行目で定義されているgreet
変数に気づかずに再定義したとします。
そうすると、既に他のscript
タグ内でgreet
変数は定義されてしまっているため、Uncaught SyntaxError: Identifier 'greet' has already been declared
というエラーが起きてしまいます。
コードの影響範囲が大きくなることで思わぬバグを生みやすいのでスコープは狭くした方がいいというのが一般的な考えです。
<body>
<!-- 1行目 -->
<script>
const greet = 'おはよう';
</script>
<!-- 100行目 -->
<script>
console.log(greet);
</script>
<!-- 200行目 -->
<script>
const greet = 'こんにちは';
</script>
<script>
console.log(greet);
</script>
</body>
モジュール化
先程の話の続きだと、scriptタグのままだと名前空間がグローバルになるという話をしました。その問題を解決するのがモジュール
です。
このようにtype="module"
を付与することで、名前空間がscript
の中だけで収まるようになり、同じファイルの中でも同じ変数名が衝突せずに参照することができます。
<body>
<script type="module">
const greet = 'おはよう';
console.log(greet);
</script>
<script type="module">
const greet = 'こんにちは';
console.log(greet);
</script>
</body>
まとめ
モジュール化を行うことで、名前空間(スコープ)を狭くできるので変数名などの衝突を防ぐことができます。
一般的には、type="module"
ではなく、ファイル分割によってモジュールを読み込んでいくので、今後はExport/Import
について深掘りしていきます。