jQueryで「ページが読み込まれたら〇〇する」という処理を書く際、$(function() {})・$(document).ready()・window.onload など複数の書き方があります。この記事では各書き方の実行タイミングの違い・使い分け・よくある落とし穴まで解説します。
この記事でわかること
- $(function() {}) と $(document).ready() の違い(実は同じ)
- DOMContentLoaded と window.load の実行タイミングの違い
- 複数の $(function) を書いた場合の動作
- 動的に追加した要素へのイベントバインド
- モダンJSでの document.addEventListener との比較
ページロード系メソッドの実行タイミング比較
| 書き方 | 実行タイミング | 画像・CSSの読み込み |
|---|---|---|
$(function() {}) |
HTML解析完了(DOMContentLoaded) | 待たない |
$(document).ready(fn) |
同上(全く同じ) | 待たない |
$(window).on("load", fn) |
全リソース読み込み完了 | 待つ |
window.onload = fn |
全リソース読み込み完了 | 待つ |
| bodyの末尾にscript | DOMContentLoaded相当(実質) | 待たない |
通常は $(function() {}) を使います。画像のサイズ取得など画像読み込みを待つ必要がある場合は $(window).on("load", fn) を使います。
$(function() {}) の基本的な使い方
// 3つの書き方はすべて同じ意味
$(function () {
// DOMが準備できたら実行
console.log('DOM ready');
});
$(document).ready(function () {
console.log('同じタイミング');
});
jQuery(function ($) {
// $がjQueryと衝突するライブラリと組み合わせる際はこの形式
console.log('$ を引数で受け取る形式');
});
$(function) を複数書いても全て実行される
ファイルを分けて複数の
ファイルを分けて複数の
$(function() {}) を書いても、jQueryが内部でキューに積んで全て実行します。window.onload = fn は最後の代入だけが有効なので注意してください。画像・外部リソース読み込み後に実行する
// ページ全体のリソース(画像・CSS・フォント)が読み込まれてから実行
$(window).on('load', function () {
// 画像の実際のサイズを取得する場合はここで
var imgHeight = $('#hero-image').height();
console.log('画像の高さ:', imgHeight);
});
// 特定の画像だけ読み込み完了を待つ
$(function () {
$('#product-img').on('load', function () {
console.log('商品画像の読み込み完了');
var w = $(this).width();
var h = $(this).height();
console.log('サイズ:', w, 'x', h);
});
});
動的に追加した要素へのイベントバインド
$(function(){}) は DOM読み込み時に存在する要素にしかイベントをバインドできません。後からAjaxや append() で追加した要素にはイベントデリゲーションを使います。
$(function () {
// NG: 後から追加された .dynamic-btn にはイベントが効かない
// $('.dynamic-btn').on('click', fn);
// OK: document または親要素に委譲する
$(document).on('click', '.dynamic-btn', function () {
console.log('動的ボタンがクリックされました');
});
// 後からボタンを追加
setTimeout(function () {
$('body').append('<button class="dynamic-btn">動的ボタン</button>');
}, 2000);
});
イベントデリゲーションは親要素に近い方が効率的
$(document).on(...) は常に動作しますが、$("#container").on(...) のようにより近い親要素を指定すると処理が効率化されます。ただし document.body や document を使っても機能上の問題はありません。モダンJSとの比較
// バニラJS: DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
console.log('DOMContentLoaded');
});
// バニラJS: 全リソース読み込み後
window.addEventListener('load', function () {
console.log('全リソース読み込み完了');
});
// 既にDOMが読み込まれている場合(scriptをbody末尾に置いた場合など)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init(); // 既に読み込み済みなら即実行
}
function init() {
console.log('初期化処理');
}
まとめ
ページロード時の処理実行に関するポイントをまとめます。
$(function() {})= DOMContentLoaded(HTML解析完了・画像を待たない)$(window).on("load", fn)= 画像・CSS等全リソース読み込み後- 複数の
$(function)は全て実行される - 動的要素へのイベント: イベントデリゲーションを使う
- 新規プロジェクト:
document.addEventListener("DOMContentLoaded", fn)が標準
関連記事: ページ離脱時にアラートを表示する完全ガイド / POSTリクエストを送信する方法
よくある質問(FAQ)
Q$(function)の中でjQueryが使えません。
AjQueryのCDNや
<script src="jquery.js">が読み込まれているか確認してください。WordPressではwp_enqueue_script("jquery")を使い、テーマのfunctions.phpでjQueryを正しくエンキューしてください。jQuery(function($) {}) の形式を使うと、$ のエイリアス競合も回避できます。Q$(window).on(“load”)の中で画像サイズが0になります。
Aloadイベントが発火する前にすでに読み込みが完了している場合、イベントが発火しないことがあります。
if ($img[0].complete) { ... } else { $img.on("load", ...) }のように、既に読み込み完了しているかチェックしてから処理してください。Q$(function)と$(document).ready()はどちらを使えばよいですか?
A全く同じ動作をするため、どちらを使っても構いません。jQueryの公式ドキュメントでは短い
$(function() {}) が主に使われています。チーム開発ではどちらかに統一することを推奨します。QSPAでページ遷移ごとに$(function)を再実行したいです。
ASPA(Single Page Application)ではページ遷移時にDOMContentLoadedは発火しません。RouterやHistoryAPIのイベントをフックするか、MutationObserverでDOMの変化を監視して初期化処理を再実行する実装が必要です。React/Vue等のフレームワークを使っている場合はライフサイクルフックを使ってください。
Q$(function)の外でjQueryコードを書いてはいけませんか?
ADOM操作を行うコードは必ず
$(function) の中に書いてください。外で書くとHTMLが解析される前にjQueryが実行されてしまい、要素が見つからない状態で処理が走ります。例外として、DOM操作を行わない関数定義やグローバル変数の宣言は外に書いて問題ありません。