大量DOM操作をjQueryで行うと遅くなる理由

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はデータではなく表示システムの一部」であると理解することです。