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で使えなかった時とかにはかなり強力な手段でした。 ↩
-
1
document.addEventListener('DOMContentLoaded', func, false);
みたいに、
addEventListener
の最後の引数にfalse
を入れてる物も良く見ますが、 最近のブラウザであればこれはデフォルトでfalse
で省略可能です。Firefox 6とかだときちんと入れないと動かない、ということですが、 流石にもうそこまで考える必要はないと思います。