ある案件で、IEだけ、$(window).on (‘load’)の中に書いてあるscriptが読まれていないことが判明し、原因がわからずあたふたしてしまいました。

問題は自分がちゃんと、jQueryの下のやつを無意識で使っていたことが原因でした。

この記述は、「htmlを読み込んでから処理を実行する」という意味です。この記述は、画像などを除いて、HTML(DOM)の読み込みが終わったら、function()の中のscriptを実行するという意味です。基本、jQueryはDOMを操作するための言語なので、それが全部読み込まれていないまま処理を実行すると大抵正しく動作しないので、大抵上の記述をしています。自分は、無意識に書いていたので、はまってしまいました。

イベントが起こる順番

  1. ページの読み込みが始まる
  2. HTML(DOM)の読み込みが終わる
  3. $(function(){ ここのプログラムが実行される });←いわゆるdocument-ready
    1. 注記:3.で例えば画像の大きさを取得しようとしてもできない
  4. 画像や動画など含めすべてのページにあるコンテンツが完全に読み込まれたら実行される
  5. $(window).on('load', function(){ここのプログラムが実行される });

ハマった原因

自分はなんでハマったかとおいうと、下記のような記述をしてしまったからです。

おそらく、HTML(DOM)の読み込みが終わって、中身を読み込む時に、画像などの読み込みが完了しておらず、$(function(){ ここのプログラムが実行される });を出てしまい、結果実行されず終わってしまったのが原因かと思います。

ちなみに、これがjQuery2系だったら実行されていたかもしれませんが、自分は3系を使っていたので実行されませんでした。なぜなら、jQuery3系はdocument-readyが常に非同期だからです。

document-ready処理が追加された時点で既にreadyでも同期的に処理を行わず、あくまで非同期で処理を行うようになります。jQuery 3.0はPromises/A+標準に従うようにしているからです。documentがreadyかどうかにかかわらず、処理の順序の一貫性を保証できます。

引用:【翻訳まとめ】jQuery 3.0 アップグレードガイド / コアの処理について

 

ちなみに自分の場合、案件ではchromeやfirefoxでは正しく動いていて、IEでは動く時と動かない時がありました。これは、仮説ですが画像がとても多いページだったので、IEでは画像が全て読み込まれず非同期処理で$(function(){ ここのプログラムが実行される });を出てしまい、結果、実行されず終わってしまったのだと思います。

$(document).readyの中身

$(document).readyの中身をgithubにある、jQueryの中身(実態はJS)を見てみましょう。

https://github.com/jquery/jquery/blob/master/src/core/ready.js

ready.jsには、$(document).readyの中身が書いてありますが、おそらくフックになってるのが、上の2行です。

document.addEventListener( "DOMContentLoaded", completed );

  • documentは、HTMLドキュメント(タグとか)
  • addEventListener はイベント登録のメソッド
  • DOMContentLoaded イベントは、最初のHTMLドキュメントの読み込みと解析が完了した時、 スタイルシートや画像、サブフレームの読み込みが終わるのを待たない

window.addEventListener( "load", completed );

  • ページが完全に読み込み終わったことを検知する時は、load

つまり、ready.js($(document).ready)は、HTMLドキュメントが読み終わった時にも実行されるし、ページの全要素が読み込まれた後にも実行されるようになっている。おそらく、DOMContentLoadedでイベントハンドラ呼び出しが失敗した場合。windowのloadイベントでもイベントハンドラが呼ばれる安心設計になっていると考えられます。安心・大切だね。

まとめ

document-readyにたいして、僕はあまりにも無意識すぎた。

参考