LoginSignup
7
2

More than 5 years have passed since last update.

append処理が重かったのでjs処理のリファクタ

Posted at

はじめに

コードを書いていてjavascriptの処理が重く、どうにか改善できないかと模索していたところ高速化できたのでその共有

要件

ボタンを押したらテーブルの末尾に行を追加する

コード

index.php
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  </head>

  <body>
    <button id='append_button'>テーブル行追加ボタン</button>
    <table border='1' id='my_table'>
      <thead>
        <tr>
          <th>header_A</th>
          <th>header_B</th>
        </tr>
      </thead>

      <tbody>
        <?php for($i=0; $i<10; $i++){ ?>
        <tr>
          <td>body_A_<?php echo($i); ?></td>
          <td>body_B_<?php echo($i); ?></td>
        </tr>
        <?php } ?>
      </tbody>
    </table>

    <script type="text/javascript" src="sample.js"></script>
  </body>
</html>
sample.js
$('#append_button').on('click', function(){
  console.time('timer');
  let tr = "<tr><td>a</td><td>b</td></tr>";
  $('#my_table').append(tr);
  console.timeEnd('timer');
});

スクリーンショット

Ze9vAoAGFN.gif

計測結果

テーブル行数 実行時間
1行 2.9ms
10行 3ms
100行 3.3ms
1000行 3.5ms
10000行 5ms
100000行 14ms

元のテーブルの行数を変えて計測しました
行数が多いほど処理に時間がかかることが分かります

原因

$('#my_table').append(tr);
テーブルを見つけそれの末尾にtrを足すだけですが、この末尾を探す処理に時間がかかっているようです
今回の例では1行の時に比べて100000行になると約5倍の差が出ました。
14msであれば改善しなくても良いかもしれませんが、実際に直面した事例では他の要因もあり改善しなければなりませんでした。

改善案

末尾を探すのに時間がかかっていたので末尾に目印をつけておき、そこに対して要素を追加してあげる
やりたいのは「末尾を探して要素を追加」ではなく「末尾に要素を追加」ということ

改善コード

index2.php
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  </head>

  <body>
    <button id='append_button'>テーブル行追加ボタン</button>
    <table border='1' id='my_table'>
      <thead>
        <tr>
          <th>header_A</th>
          <th>header_B</th>
        </tr>
      </thead>

      <tbody>
        <?php for($i=0; $i<10; $i++){ ?>
        <tr>
          <td>body_A_<?php echo($i); ?></td>
          <td>body_B_<?php echo($i); ?></td>
        </tr>
        <?php } ?>
        <tr id='last_tr' style='display: none;'>
          <td>dummy_A</td>
          <td>dummy_B</td>
        </tr>
      </tbody>
    </table>

    <script type="text/javascript" src="sample2.js"></script>
  </body>
</html>
sample2.js
$('#append_button').on('click', function(){
  console.time('timer');
  let tr = "<tr><td>a</td><td>b</td></tr>";
  $('#last_tr').before(tr);
  console.timeEnd('timer');
});

改善後の計測結果

テーブル行数 実行時間
1行 1.5ms
10行 1.6ms
100行 1.6ms
1000行 1.5ms
10000行 1.8ms
100000行 1.6ms

平均をとっていてバラつきはありますが、行数に依存しない処理速度が確保できました。
改善前の100000行と比べると10倍の改善になりました:smile:

おわりに

些細なことですがうっかり大きいテーブルにappendすると処理時間がかかるので、こういうテクニックを覚えておくと良いかもしれません。
また、dummyの要素を末尾においているので場合によっては副作用をもたらすこともありそうですね。
注意して参考にしてみてください。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2