- jQueryが遅くなるのは「数が増えたとき」
- DOMは配列ではない
- jQuery特有のコスト
- 典型的な遅いコード
- なぜ途中から急に遅くなるのか
- もう1つの落とし穴「再検索」
- 最も重い処理「読み取り+書き込み」
- 正しい対処法
- 実務で起きやすい場所
- 注意点
- 最後に
jQueryが遅くなるのは「数が増えたとき」
jQueryは少量のDOM操作では問題になりません。
しかし要素数が増えた瞬間に急に重くなることがあります。
これはjQueryのアルゴリズムが悪いわけではなく、DOMという仕組みの特性と、jQueryの設計が組み合わさって発生する現象です。
多くの開発者が遭遇するパターンがあります。
PCでは問題なく動くのに、本番データやスマートフォン環境で突然遅くなります。
その原因の大半は「大量DOM操作」です。
DOMは配列ではない
まず理解すべき重要な点があります。
DOMはJavaScriptの配列のようなデータ構造ではありません。
DOMは画面そのものです。
JavaScriptの配列に1000件追加しても、メモリが少し増えるだけです。
しかしDOMに1000件追加すると、ブラウザは次の処理を行います。
- ノード生成
- ツリー構造の更新
- スタイル計算
- レイアウト計算
- 描画
つまり、DOMを1つ増やすたびに「画面を作り直す準備」が発生します。
$(".list").append("<li>item</li>");
この1行は、単なる文字列追加ではありません。
ブラウザの描画エンジンを動かしています。
jQuery特有のコスト
jQueryを使うと、DOM操作の前に追加の処理が入ります。
$(".item").addClass("active");
内部で行われる処理:
- CSSセレクタ解析
- 要素探索
- jQueryオブジェクト生成
- コレクション化
- ループ処理
- DOM更新
つまり、DOMのコストに加えて抽象化レイヤーのコストが上乗せされます。
1回では小さい差ですが、1000回繰り返すと無視できなくなります。
典型的な遅いコード
次のようなコードは非常によく見かけます。
for (let i = 0; i < 1000; i++) { $(".list").append("<li>"+i+"</li>"); }
これは1000回のDOM追加です。
そして1000回のレイアウト更新の可能性があります。
さらに毎回
- セレクタ検索
- jQueryラップ生成
が発生します。
これが「最初は速いのに途中から固まる」原因です。
なぜ途中から急に遅くなるのか
DOMは増えるほど処理が重くなります。
理由は、レイアウト計算が相互依存しているためです。
例えば、
- 10個の要素 → 計算範囲は小さい
- 1000個の要素 → ページ全体に影響
ブラウザはツリー構造を上から下まで再評価します。
そのため、処理時間は線形ではなく体感的には指数的に重くなります。
もう1つの落とし穴「再検索」
多くのコードでは、同じ要素を何度も取得しています。
for (let i = 0; i < 500; i++) { $(".item").eq(i).addClass("active"); }
このコードでは、500回セレクタ検索が行われます。
`.item`は毎回DOMツリー全体を探索します。
改善するとこうなります。
const items = $(".item"); for (let i = 0; i < items.length; i++) { items.eq(i).addClass("active"); }
検索は1回です。
これだけで体感速度が大きく変わることがあります。
最も重い処理「読み取り+書き込み」
さらに危険なのがこれです。
$(".row").each(function(){ $(this).width($(this).width() + 10); });
これは毎回
1 レイアウト情報取得
2 ブラウザ再計算
3 サイズ変更
4 再計算
を繰り返します。
要素数分reflowが発生します。
結果としてCPUが占有され、スクロールやクリックが効かなくなります。
正しい対処法
基本は「まとめて操作」です。
悪い例:
for(let i=0;i<1000;i++){ $(".list").append("<li>"+i+"</li>"); }
改善:
let buffer = ""; for(let i=0;i<1000;i++){ buffer += "<li>"+i+"</li>"; } $(".list").html(buffer);
DOM更新は1回だけです。
さらに良い方法として、DOMから一時的に外す手もあります。
const list = $(".list").detach(); list.append(buffer); $("body").append(list);
画面に存在しない間はレイアウト計算が行われません。
実務で起きやすい場所
特に遅くなりやすいUIがあります。
- テーブル行の大量追加
- 無限スクロール
- チャットログ表示
- 検索結果一覧
- 管理画面のリスト
データ件数が増えた途端に遅くなる場合、まずDOM操作を疑うべきです。
注意点
jQueryをネイティブに置き換えるだけでは解決しないケースも多いです。
問題は「jQuery」ではなく「DOMの扱い方」です。
ネイティブでも以下は遅くなります。
for(let i=0;i<1000;i++){ const li=document.createElement("li"); list.appendChild(li); }
本質は同じです。
最後に
大量DOM操作で遅くなる理由は、JavaScriptの速度ではありません。
ブラウザが画面を維持するために行っている計算量です。
jQueryはDOM操作を簡単にしました。
しかし簡単になったことで、画面を再構築している感覚が失われました。
パフォーマンス改善の第一歩は、
「DOMはデータではなく表示システムの一部」であると理解することです。