JavaScriptやjQuery関連のサイトを見ていると、
window.onload $(document).ready $(window).on('load'
の実行順序についての解説は沢山ある。
今日、ワテもある簡単なJavaScriptプログラムを書いていてこれらの関数で少々混乱した。
以下、その備忘録。
window.onload が二つ以上あると最後のやつしか実行されない
ワテのブログでは、幾つかのページにJavaScriptのサンプルプログラムが動くようにしている。
例えばこれらのページ。
【これは便利】JavaScriptのPromiseを多段連結する
JavaScriptでSetTimeoutを使って他の処理が終わったかどうか調べる
その中では、WordPressのカスタムフィールドに自作のJavaScriptプログラムのコードを埋め込んでいる。
ページが読み込まれた時点で実行したいので、コードの冒頭ではwindow.onload を使っている。
今までそれで問題無く動いていたのだが、今日、上記のサンプルプログラムが動いていない事に気づいた。
良く調べてみると、数日前の改良でそれらとは別のプログラムをページに追加したのだがそこでもwindow.onload を使っていた。
その改良とはこれだ。
【ワテのオープンソース】ハイライト表示プラグインhighlight.jsを拡張する【表示幅を広げる】
ネットを検索して、window.onload は二つ以上あっても最後のやつしか動かない事が判明して解決。
念のために、window.onload $(document).ready $(window).on(‘load’ に付いても調査してみた。
window.onload, $(document).ready, $(window).on(‘load’ の実行順序や複数定義の場合の挙動調査
以下のようなテストプログラムを即席で書いてみた。
ここで別の問題に気付いた。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script> <!--<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>--> <!--<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>--> <!--<script src="Scripts/jquery-3.1.0.js"></script>--> </head> <body> <script type="text/javascript"> //① jQueryの場合 //chromeの場合にこの二つの実行順序は1➜2もあれば2➜1もあった。 $(document).ready(function () { alert("$(document).ready( を使う1。"); }); $(document).ready(function () { alert("$(document).ready( を使う2。"); }); //②chromeで数回試したが、実行順序は1➜2のようだ $(window).on('load', function () { alert("$(window).on('load' を使う1。"); }); $(window).on('load', function () { alert("$(window).on('load' を使う2。"); }); //③ .load() はDeprecated(非推奨)なのだが、jquery-3.1.0.js では // // jquery-3.1.0.js:9649 Uncaught TypeError: url.indexOf is not a function // //というエラーで動かなかったので、既に廃止されているのかな。 if (false) $(window).load(function () { alert('$(window).load は廃止。今は動かない。'); }); //④ JavaScriptの場合 window.onload = function () { alert('window.onload1 二つあるとこちらは実行されない。'); } window.onload = function () { alert('window.onload2 二つあると最後のやつが実行される。'); } // 全体の実行順序はchromeの場合には、以下のようになった。 // $(window).on('load' // window.onload // $(document).ready </script> </body> </html>
その問題とは、
$(window).load(function () { ... })
がChromeでもIEでも動かない。
jquery-3.1.0.js:9649 Uncaught TypeError: url.indexOf is not a function
こんなエラーが出るのだ。
もう訳分からん。
でも、少し調べたら解決。
$(window).load(function () { ... }) 非推奨(Deprecated) $(window).on('load', function () {... }) こちらを使うと問題ない
と言う事だが、本日(2016/8/15)時点の最新の jquery-3.1.0.js では、非推奨な方式の .load() は動かないようだ。
従って、後者の .on(‘load’, を使って解決。
以下、ワテの実験で分かった幾つかの事実
$(document).ready が複数あると、実行順序は不定のようだ
$(document).ready(function () { ... }); // ① $(document).ready(function () { ... }); // ②
のように二つを実行すると、両方実行出来たのだが、必ずしもこの①➜②の順番では実行されない。数回実験したが②➜①の場合もあった。
なお実験したのはChrome。他のIEやFirefoxでは未確認。
上記のサンプルプログラムをChromeとIEで実行してみたが、その実験結果では、以下のような実行順序となった。
JavaScriptとjQueryのload, ready関数の実行順序の調査結果
ワテの実験では以下のようになった。
window.onload 複数あると最後のやつが実行さる
$(document).ready 複数あっても全部実行される。実行順はランダムに変わる。
ただし、本来は
$(document).ready(function(){ ... });
はHTML documentが読み込まれた時点で実行。
$(window).on('load', function() { ... });
はその後でHTML documentだけでなく、ページ内でリンクが張られている全てのリソース(例えば画像、CSSスタイルなど)が読み込まれた時点で実行。
と言うふうに多くのブログサイトなどで説明されている。
しかし、今回のワテの実験では画像もCSSも無い簡素なページではこの規則通りには行かずに、先に on(‘load’ が実行され、次に ready が実行される場合も有る事が判明した。
要注意だ。
その理由は何だろうか?
推測するなら、恐らく、画像もCSSも無い簡素なページだと、一瞬でページのhtmlテキストデータが読み込まれる訳だから、ready条件達成とload条件達成の判定がほぼ同時になるのかもしれない。
その結果、ブラウザーさんが混乱して間違うのかも知れない。
まとめ
JavaScript, jQueryを約一年くらいやって来たが、
$(window).on('load' window.onload $(document).ready
の使い方は、何回覚えても忘れる。
今回の収穫は、
$(window).load(function () { ... }) // 非推奨(Deprecated)なので使わないようにする $(window).on('load', function () { ... }) // もし使うならこちら
と言う事か。
また、ページ読み込み時に実行したい処理は、
$(window).on('load', function () { ... }) $(document).ready(function () { ... })
のどちらかを使っておけば良い。
これらを使っておけば、もし誰か別の人が同じページで load や ready の処理を追加していてもかち合う事は無い。
と言う事か。
重要な発見
さらに、この二つは全く同じ物。
$(function() { ... }); $(document).ready(function () { ... });
らしい。知らなんだ。
最近のワテの記述スタイル
と言う事で、最近のワテの場合はHTMLページをロードした直後に実行したい処理は、以下の例のように書くようにしている。
<script> $(function(){ ... // ページをロードした直後に実行したい処理1 }); $(function(){ ... // ページをロードした直後に実行したい処理2 }); </script> <script> $(function(){ ... // 必要なら<script>ブロックを複数入れても良い。処理3 }); </script>
なお、複数の $(function(){ … }); を入れている場合には、どれが先に実行されるのかは恐らく保証されていないと思う。
ブラウザーによっても異なる可能性があるだろう。
なので、どっちが先に実行されても良いようにプログラムを書いておくと良いだろう。
より最近のワテのスタイル
あるいはjQueryを使わずにピュアなJavaScriptで書くなら、こんな感じか。
// ワテのお勧め
document.addEventListener("DOMContentLoaded", function(){
...
});
ワテは、最近は、専ら(もっぱら)この記法を採用している。
WEBプログラミングの本を読む
アマゾンでランキングの高い二冊を選んでみた。
コメント
素晴らしい記事をありがとうございます!
風吹けば名無し様
この度は小生の記事にコメント有難うございました。
数年前まではWEBプログラミングに熱中していて、その当時jQueryやJavaScriptを独学していて色々と実験しました。
この記事で紹介した内容は、ブラウザーの種類やバージョン、jQueryのバージョンなどでも変わると思いますので、必ずしも最新の情報ではありません。
ですので、もし必要なら記事で紹介しているhtmlサンプルなどを参考にして頂きまして、最新状況をお試しください。