JavaScript のロード時に HTML 要素が取得できないやつ

JavaScript でコードの記述によって実行タイミングが違うので HTML 要素が取得できない場合があります。

仕事中にちょっとハマってしまったのでメモ。 自分でまとめないと忘れると思うので。
冷静になればすぐわかることなんですがね…。

確認したこと

具体的な内容は以下のタイミングで取得できるかどうかです。

  • JavaScript 読み込み時
  • $(document).ready()
  • window.onload()

これらを取得する要素の前後で実行します。

コード

HTML

jQuery をロードして<div>の前後に before.js と after.js を記述。

<!DOCTYPE html>
<html>
<head>
</head>
<body>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="./before.js"></script>

<div id="test"></div>

<script src="./after.js"></script>

</body>
</html>

JS

before.js と after.js の内容。

before.js 出力はconsole.log('before XXXX : ' + $('#test')[0]);にしています。

console.log('after init : ' + $('#test')[0]);
$(window).on('after load', onload);

$(function() {
  console.log('after ready  : ' + $('#test')[0]);
});

function onload() {
  console.log('after onload : ' + $('#test')[0]);
}

結果

IE11 で確認。 この程度はブラウザに依る差異はないと思います。

f:id:s4_ba:20151115101133j:plain

before init のみ取得できませんでした。

なぜこうなるのか

init は JavaScript のロード時に実行されます。

before init は取得する要素が DOM にロードされる前に実行され、 after init は取得する要素が DOM にロードされた後に実行されます。

before init では DOM にロードされる前に要素を取得しようとしたため undefined になります。

ready は HTML のロード後、load はすべてのコンテンツのロード後に実行されるため、取得できます。 また、上書きではなくスタックされていくので before も after も実行されます。

まとめ

JavaScript は body の最後に記述しよう!!