ライブラリ以外はとりあえず type="module" にしよう
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ 最後に実行してくれるので DOM 構築後に実行するためのリスナ登録不要
◆ defer では無理だったインラインコードでもあとで実行される
◆ head/body タグ省略時で body の最後に script タグを書くのが難しい場合にも助かる
◆ defer では無理だったインラインコードでもあとで実行される
◆ head/body タグ省略時で body の最後に script タグを書くのが難しい場合にも助かる
ただのスクリプトなら type を書かなくていいので わざわざ書くのは面倒です
だけど type="module" を書いておくべきだと思います
import/export を使うには module であることが必須です
head タグに書くと body 要素がないから body の最後に書く なんてことを考えなくてすみます
特に head/body タグを省略して body の中身がなにもない場合は head タグ中に script が書かれてると扱われて body がないケースがあります
この script は head タグ中として処理され 実行中に body タグはありません
このために body で囲むか
body 中にしか配置できないタグを先に書いておく必要があります
必要なタグならこれでいいですが body タグ内で script タグを実行させるためにだけにいらないものを配置するのは良い方法とは言いづらいです
head タグ中で実行されても window.onload などリスナ登録すればいいだけとは思いますがそれも毎回になると面倒です
しなくていいなら せずに済ませたいものです
script タグでも defer を設定することで DOM 構築後に実行することは可能でした
しかしそれは別 URL からロードするための機能なので script タグ中に JavaScript を書いている場合には意味がなく即実行されました
module の場合はインラインスクリプトであっても DOM 構築後に実行してくれます
これは問題なく動きます
トップレベルに変数を作ってもグローバル変数にはなりません
グローバルに起きたくないから無名関数の即時実行をする ということは不要になります
と言っても window のプロパティへ代入すればグローバル変数を作ったり編集したりすることは可能です
あとは強制 strict モード
あまり大きな違いはないものの 一部のワードがキーワードになって変数に使えなかったり いらない引数を捨てるために _ を 2 回引数名に使うとエラーになったりときどき鬱陶しく感じます
スコープの違いがデメリットになる場合もあります
グローバルにおいても困らないものはグローバルにあるほうがデバッグ時には楽です
コード自体をいじらなくとも devtools のコンソールだけでだいたいのことはできてしまいます
しかし グローバルから何も参照できない状態だとコンソールでできることも限られます
ライブラリがモジュール中から import される場合 自分でグローバルに公開しない限り グローバル空間で実行されるコンソールから参照できません
ちょっと動き試すときにも関数が使えなかったり デバッグ時の手間はけっこう増えます
例えば jQuery 使ってる人だと コンソールから $ で jQuery 使うことがあると思いますが グローバル変数じゃなくなるのでコンソールでは $ が使えなくなるというようなものです
devtools のコンソールでコードを実行空間をモジュール単位で変更できるようになればいいのですけどね
だけど type="module" を書いておくべきだと思います
module
まず機能面で module を使うには書いておかないとダメですimport/export を使うには module であることが必須です
実行タイミング
また type="module" のスクリプトの実行は最後に行われますhead タグに書くと body 要素がないから body の最後に書く なんてことを考えなくてすみます
特に head/body タグを省略して body の中身がなにもない場合は head タグ中に script が書かれてると扱われて body がないケースがあります
<!doctype html>
<script>console.log(1)</script>
この script は head タグ中として処理され 実行中に body タグはありません
<!doctype html>
<body><script>console.log(1)</script></body>
このために body で囲むか
<!doctype html>
<div></div>
<script>console.log(1)</script>
body 中にしか配置できないタグを先に書いておく必要があります
必要なタグならこれでいいですが body タグ内で script タグを実行させるためにだけにいらないものを配置するのは良い方法とは言いづらいです
head タグ中で実行されても window.onload などリスナ登録すればいいだけとは思いますがそれも毎回になると面倒です
しなくていいなら せずに済ませたいものです
script タグでも defer を設定することで DOM 構築後に実行することは可能でした
しかしそれは別 URL からロードするための機能なので script タグ中に JavaScript を書いている場合には意味がなく即実行されました
module の場合はインラインスクリプトであっても DOM 構築後に実行してくれます
<!doctype html>
<script type="module">document.body.innerHTML = "1"</script>
これは問題なく動きます
スコープ
module の場合はスクリプトはグローバル空間で実行されませんトップレベルに変数を作ってもグローバル変数にはなりません
グローバルに起きたくないから無名関数の即時実行をする ということは不要になります
と言っても window のプロパティへ代入すればグローバル変数を作ったり編集したりすることは可能です
デメリット
一番感じるデメリットは type="module" 書くのが面倒 これだと思いますあとは強制 strict モード
あまり大きな違いはないものの 一部のワードがキーワードになって変数に使えなかったり いらない引数を捨てるために _ を 2 回引数名に使うとエラーになったりときどき鬱陶しく感じます
スコープの違いがデメリットになる場合もあります
グローバルにおいても困らないものはグローバルにあるほうがデバッグ時には楽です
コード自体をいじらなくとも devtools のコンソールだけでだいたいのことはできてしまいます
しかし グローバルから何も参照できない状態だとコンソールでできることも限られます
ライブラリがモジュール中から import される場合 自分でグローバルに公開しない限り グローバル空間で実行されるコンソールから参照できません
ちょっと動き試すときにも関数が使えなかったり デバッグ時の手間はけっこう増えます
例えば jQuery 使ってる人だと コンソールから $ で jQuery 使うことがあると思いますが グローバル変数じゃなくなるのでコンソールでは $ が使えなくなるというようなものです
devtools のコンソールでコードを実行空間をモジュール単位で変更できるようになればいいのですけどね