JavaScriptでページを読み込み後に何かを行いたいときは
window.onload = function()を使ったり、jQueryを使っていれば
$(document).ready(function())を使ったりしますが、
これらはちょっと違うものです。
特にjQuery無しで$(document).ready(function)的な事をするのが
ちょっと面倒ですがその辺について。
window.onload
window.onloadメソッドはonloadイベント発生時に実行されますが、
これはDOMツリーの構築だけでなく、画像や他の全てのデータの
読み込みが完了した時、になります。
また、
1 2 3 | |
の様にonloadに値を1つ与える形になるので、
この後で
1 2 3 | |
の様にすると、この最後に指定されたものだけが実行されます(‘onload 2’だけ表示される)。
また、document.body.onloadを指定することも出来ますが、
基本的にwindow.onloadと同じ動作をしますが、
ブラウザによって違う場合があるので使うならwindow.onloadを使うべきです。
$(document).ready
jQueryを使ってる時にはよく使う形。
こちらは画像の読み込みなどは待たず、 DOMツリーの構築が終わった時点で実行されます。
従って、window.onloadで指定されているものよりも先に実行されます。
1 2 3 | |
これは複数書いてもそれら全てが実行されます。
documentもreadyも短縮して
1 2 3 | |
と書くことも出来ます。
また、$が他と衝突するような場合、
1 2 3 | |
という感じの書き方になります。
また、
onを使って、
1 2 3 | |
と書いても同じような動作になります。(が、下に書くように上のものと区別する必要があります。)
jQuery無しで$(document).readyな呼び出しをする
window.onloadとjQueryの$(document).readyは
呼び出されるタイミングが違うのと、
複数の処理を別々に与えられるかどうか、の違いが有ります。
タイミングについてはDOMツリーが出来てればJavaScriptでしたいことは出来ることが多いので 画像とかの読み込みを待たずに実行したいことが多いかと思います。
また、別々の場所で必要に応じてやりたいことを追加できる方が便利です。
なので、jQueryがない場合でも$(document).ready的な事をしたいわけです。
これを行うには
DOMContentLoadedイベントに対して
イベントリスナーを追加します1。
1 2 3 | |
こんな感じ。
DOMContentLoadedは文字通りDOMが出来上がった時で、
jQueryの中のreadyも実際にはDOMContentLoadedを使ったりしして
実装されています2。
addEventListenerでの追加は複数行っても全て実行されます3。
今はIEやSafariなんかでもこのDOMContentLoadedを使える4
のでこれで$(document).readyと殆ど同じ動作として使うことが出来ます。
onload時に行う物を複数登録する
一方で画像などを全て読み込んだ後にやりたいこともあるかもしれません。
そのような時はwindow.onloadを使えば良いのですが、
これだと1つしか指定できません。
こんな時はjQueryを使えば
1 2 3 | |
としたり、
1 2 3 4 5 6 7 | |
みたいに、event.addを使ったり、onを使って書くことが出来、
これらはload時に実行され、
また、複数加えても加えた分だけ実行されます。
これをjQueryなしでやるには
1 2 3 4 5 6 7 8 9 10 11 | |
見たいな感じでwindowへイベントリスナーを加えたいわけですが、
IEとかだとwindowにはaddEventListenerの代わりに
attachEventというメソッドが用意されてるので
それを使う様にします。引数もloadとonloadで違います5。
addEventListenerとattachEventでカバーできない物は殆ど無いと思いますが、
もし他でonload =してる場所が無ければ(もしくはここで上書きしても良いのなら)ここでonload =を最後に
加えることも出来ます。
実行される順序
上に書いたとおり、readyの物の方がloadの物よりも先に実行されます。
ではそれらの中では順序はどうなるか、テストしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
ここでは
- load:
window.onload = function() {...window.addEventListener("load", function() {...$(window).load(function() {...(jQuery)$(window).on("load", function() {...(jQuery)$.event.add(window, "load", function() {...(jQuery)
- ready:
document.addEventListener("DOMContentLoaded", function() {...$(document).ready(function() {...(jQuery)$(function() {...(jQuery)
を使っています。
ついでに間に即時呼び出し関数式(Immediately-invoked function expression, IIFE)(function() {...も挟んであります。
これを実行すると、Google Chrome(43.0.2357.130, Mac)だと
IIFE 0
IIFE 1
IIFE 2
ready 0 $(document).ready(function() {...
ready 0 $(function() {...
ready 1 $(document).ready(function() {...
ready 1 $(function() {...
ready 0 $(document).on("ready", function() {...
ready 1 $(document).on("ready", function() {...
ready 0 document.addEventListener("DOMContentLoaded", function() {...
ready 1 document.addEventListener("DOMContentLoaded", function() {...
load 0 window.addEventListener("load", function() {...
load 0 $(window).load(function() {...
load 0 $(window).on("load", function() {...
load 0 $.event.add(window, "load", function() {...
load 1 $(window).load(function() {...
load 1 $(window).on("load", function() {...
load 1 $.event.add(window, "load", function() {...
load 1 window.onload = function() {...
load 1 window.addEventListener("load", function() {...
一方、Firefox(39.0, Mac)でみると、
殆ど同じ順序ですが、load 1 window.onload = function() {...が
load 0 window.addEventListener("load", function() {...の前に来ます。
ちょっと色々テストしてみると
readyに関して:- まず、
$(document).ready、または$(function()等のjQueryのいわゆるdocument readyな物が最初に順に実行される。 - 次に
$(document).on("ready"な物が実行される。 - その後、
"DOMContentLoaded"の物が実行される。
- まず、
loadに関して:window.onloadは最後に書かれたものだけが実行される。window.onloadとaddEventListener("load"は、記述された順序で実行される。ただし、window.onloadが2つ以上ある場合、 最初に書かれた所が基準になる。- 上の例で、2つ目の
load 1 window.onloadが一番最後に書かれたとしても、load 0 window.onloadの位置が基準になるので、load 1 window.addEventListener("load"よりも先にload 1 window.onloadが実行される。
- 上の例で、2つ目の
$(window).load、$(window).on("load"、$event.add(window, "load"のjQueryな物はこれらの中では記述通りの順序が保たれる。- Firefoxでは
window.onloadとaddEventListener("load"な物は、 jQueryのloadに関するものの全てより先にあれば先に実行される。- もし、jQueryの
loadの物が一つでも先にあれば、全てのjQueryのものより後で実行される。 - この時も
window.onloadの基準は一番最初の物。
- もし、jQueryの
- Google Chromeでは
addEventListener("load"な物は jQueryのloadに関するものの全てより先にあれば先に実行される。- もし、jQueryの
loadの物が一つでも先にあれば、全てのjQueryのものより後で実行される。
- もし、jQueryの
- Google Chromeでは
window.onloadは何処に書いても全てのjQueryのloadのものより後で実行される。
と言った感じの順序です。
ちょっとごちゃごちゃしてしまいますが、
要するに色々使うと結構前後する可能性があるので
特別な理由がない限りloadやready内では統一した書き方で
書くべきだ、と。
-
javascript - $(document).ready equivalent without jQuery - Stack Overflow ↩
-
実際にはもっと複雑に
DOMContentLoadedが使えないブラウザの場合には それをエミュレートしたりしています。その昔、IEとかSafariで使えなかった時とかにはかなり強力な手段でした。 ↩
-
1document.addEventListener('DOMContentLoaded', func, false);みたいに、
addEventListenerの最後の引数にfalseを入れてる物も良く見ますが、 最近のブラウザであればこれはデフォルトでfalseで省略可能です。Firefox 6とかだときちんと入れないと動かない、ということですが、 流石にもうそこまで考える必要はないと思います。
