【JS】グローバル変数の衝突でエラーが発生したけど type="module" で解決できた
どういうことがあったか
すでに運用されているサイトの一部のページを制作することになり、
自分が作成した JS とは別に、サイト共通で使用されている JS も読み込む必要があった。
<script src="/common.js"></script><!-- 共通ファイル -->
<script src="/new/script.js"></script><!-- 自分が作成した新ファイル -->
これらの JS ファイル間で変数名が衝突してしまい、結果としてエラーが発生してしまっていた。
// /common.js
const a = 123;
// /new/script.js
const a = "abc";
※上記あくまでイメージ。
共通ファイルを変えてもらうわけにもいかず、
新ファイルのほうの原因である変数は npm パッケージで使われているもので、簡単に変更することもできない。
type="module"
解決:結論としては、以下のように新ファイルの読み込みに type="module"
を追加して解決しました。
(共通ファイルの読み込みについては、予期せぬところで影響があっては困るのでそのままとしました。)
<script src="/common.js"></script>
<script src="/new/script.js" type="module"></script>
type="module"
(JavaScript モジュール)とは
script
タグに type="module"
を指定することで、読み込むファイルは JavaScript モジュールとして扱われます。
module: コードを JavaScript モジュールとして扱います。
https://developer.mozilla.org/ja/docs/Web/HTML/Element/script#attr-type
JavaScript モジュールは、 import
と export
文を用いてインポート・エクスポートができる形式です。
モジュールスクリプトの通常のスクリプト(クラシックスクリプト)の違いのうち、今回重要なのはこの部分です。
最後ですが重要なこととして明らかにしておきますが、モジュールの機能は単独のスクリプトのスコープにインポートされます。つまり、インポートされた機能はグローバルスコープから利用することはできません。それゆえ、インポートされた機能はインポートしたスクリプトの内部からしかアクセスできず、例えば JavaScript コンソールからはアクセスできません。文法エラーは開発ツール上に表示されますが、使えることを期待するデバッグ技術の中には使えないものがあるでしょう。
宣言された変数や関数のスコープが閉じられており、グローバルスコープの変数や関数と衝突することがないのです。
かなり重要なことなのに今回始めて知りました。
今後はグローバル汚染を避けるために、自分が設置する script タグには基本的に type="module"
をつけておこうと思いました。
Discussion