- $(document).ready()はなぜ使われていたのか
- HTMLとJavaScriptは同時に動いていない
- DOMが完成する瞬間 ― DOMContentLoaded
- 問題はブラウザ対応だった
- $(document).ready()の本当の役割
- window.onloadとの違い
- 本当に必要だったのか
- 現在はどうなったか
- 注意点
- まとめ
$(document).ready()はなぜ使われていたのか
jQueryを触ったことがある人なら、ほぼ確実に見たことがあるのがこれです。
$(document).ready(function(){ $("#menu").hide(); });
あるいは省略形です。
$(function(){ $("#menu").hide(); });
現在のJavaScriptではほとんど見かけません。
では、これは単なる「昔の書き方」だったのでしょうか。
実は違います。
当時は、これを書かないとJavaScriptが“正しく動かない”可能性が高かったのです。
その理由は「DOMの読み込みタイミング」にあります。
HTMLとJavaScriptは同時に動いていない
Webページは、ブラウザが上から順にHTMLを読み込んで構築します。
JavaScriptはその途中で実行されます。
たとえば次のHTMLを見てください。
<html> <head> <script> document.getElementById("title").textContent = "変更"; </script> </head> <body> <h1 id="title">Hello</h1> </body> </html>
このコードはエラーになります。
理由は単純で、scriptが実行された時点でまだ<h1>が存在していないからです。
ブラウザは
1. <head>を読む
2. scriptを実行する
3. その後に<body>を読む
という順序で処理します。
つまりJavaScriptの問題ではなく、
DOMがまだ完成していないタイミングでDOM操作をしているのが原因です。
DOMが完成する瞬間 ― DOMContentLoaded
ブラウザはHTMLをすべて解析し、DOMツリーを構築した瞬間にイベントを発火します。
それが「DOMContentLoaded」です。
document.addEventListener("DOMContentLoaded", function(){ document.getElementById("title").textContent = "変更"; });
これが現代の標準的な書き方です。
DOMが構築された後に処理が実行されるため、安全に要素へアクセスできます。
では、なぜ昔はこれが使われなかったのでしょうか。
問題はブラウザ対応だった
2000年代、最大の障害はInternet Explorerでした。
古いIEはDOMContentLoadedイベントを正しくサポートしていませんでした。
つまり
- Firefoxでは動く
- IEでは動かない
という状況です。
ここで登場したのがjQueryの$(document).ready()です。
$(document).ready()の本当の役割
jQueryのreadyは単なるイベントではありません。
内部では複数の検出方法を組み合わせて「DOM完成」を判定していました。
代表的なものは以下です。
- DOMContentLoaded
- onreadystatechange
- doScroll hack(IE独自)
- loadイベントのフォールバック
つまり$(document).ready()は
「どのブラウザでもDOMが使えるタイミング」を保証する仕組み
でした。
開発者はDOMの状態を気にせず、次のように書けました。
$(function(){ $("#title").text("変更"); });
これが普及した最大の理由です。
window.onloadとの違い
よく混同されるのがこれです。
window.onload = function(){ // 処理 };
window.onloadは「ページのすべてが読み込まれた後」に実行されます。
ここで言う「すべて」には画像も含まれます。
つまり、
| イベント | 発火タイミング |
| DOMContentLoaded | HTML解析完了(DOM使用可能) |
| window.onload | 画像・CSS・外部ファイルも含め完全読込 |
画像が多いページではwindow.onloadは数秒遅れることもありました。
UI初期化を待たされるため、体感速度が悪化します。
jQueryのreadyは
「操作できる最速のタイミング」で実行されるのが重要でした。
本当に必要だったのか
結論として、当時は必要でした。
理由は次の3つです。
- DOMContentLoadedが統一されていなかった
- scriptの実行タイミング制御が難しかった
- IE対応が必須だった
つまりベストプラクティスではなく、
安全にJavaScriptを書くための前提条件でした。
現在はどうなったか
現在は次の書き方が可能です。
<script defer src="app.js"></script>
defer属性により、HTML解析後にスクリプトが実行されます。
そのためreadyは不要になりました。
あるいは次でも十分です。
document.addEventListener("DOMContentLoaded", init);
ブラウザの互換性問題が解消されたためです。
注意点
ただし1つだけ注意があります。
モジュールスクリプトです。
<script type="module" src="app.js"></script>
moduleは自動的にdefer扱いになります。
readyを書くと逆に冗長になる場合があります。
「昔の習慣」で書くと、
処理が二重に実行されるバグの原因になることがあります。
まとめ
$(document).ready()は古い書き方ではありますが、意味のないものではありません。
- DOM未完成問題を回避した
- ブラウザ差を吸収した
- UI初期化を最速化した
当時のWeb開発では「書いた方がいい」ではなく
書かないと壊れる可能性があったコードでした。
そして現在、私たちが気にせずDOMを扱えるのは、
ブラウザがようやくjQueryの前提に追いついたからだと言えます。