JavaScript

【JavaScript】記述方法別の実行タイミングについて

More than 1 year has passed since last update.

JavaScriptを記述する方法はいくつか存在するが、それぞれ実行タイミングが異なる。
ここではそれについてまとめる。

<script>タグ内に記述する

<script>タグ内にJavaScriptを記述した場合、スクリプトが実行されるのは<script>タグが解析された直後となる。そのため<script>タグ以降のDOM要素を操作することはできない。

html
<body>
<div id="a"></div>
<script>
  var a = document.getElementById('a');
  console.log(a != null); // true
  var b = document.getElementById('b');
  console.log(b != null); // false
</script>
<div id="b"></div>
</body>

また、外部のJavaScriptファイルを読み込んだ場合も同様で、<script>タグ解析後にファイル読み込みが開始され、読み込み終了後スクリプトが実行される。

html
<div id="a"></div>
<script type="text/javascript" src="demo.js"></script>
<div id="b"></div>
demo.js
var a = document.getElementById('a');
console.log(a != null); // true
var b = document.getElementById('b');
console.log(b != null); // false

onloadイベントハンドラとして記述する

この場合はページ読み込み完了後、すなわちDOMツリー構築、<img>タグによる画像ファイルの外部リソースのロードなどすべて完了した時点でスクリプトが実行される。

demo.js
// htmlは先程と同じ
window.onload = function() {
    var a = document.getElementById('a');
    console.log(a != null); // true
    var b = document.getElementById('b');
    console.log(b != null); // true <- 注目
};

そのため、画像ファイルなどのリソースが大きい場合、スクリプトの実行までに必要以上の時間がかかる可能性がある。

DOMContentLoadedイベントに対してリスナを登録する

DOMContentLoadedはDOMツリー構築完了直後、画像ファイルなどの外部リソースが読み込まれる前に発火するイベントである。このイベントに対してリスナ登録することで、イベント発火時にスクリプトを実行する。

demo.js
document.addEventListener('DOMContentLoaded', function() {
    var a = document.getElementById('a');
    console.log(a != null); // true
    var b = document.getElementById('b');
    console.log(b != null); // true
});

なお、DOMContentLoadedは、IE9、Safari3.1以降でないと対応していない模様。
DOMContentLoaded - MDN

動的ロード

script要素を生成することにより、動的にJavaScriptファイルをロードすることのできる記述方法。JavaScriptファイルのダウンロードから実行開始まで、その他の処理をブロックしないという特徴がある。

var script = document.createElement('script');
script.src = 'test.js';
document.body.appendChild(script);

なお、この記述方法は、クロスドメインでデータ取得を行う場合に利用されるJSONPという仕組みの実現にも使われる、らしい。。。

参考書籍

パーフェクトJavaScript