Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
309
Help us understand the problem. What is going on with this article?
@mah_lab

jQueryのパフォーマンスを下げるアンチパターンに関する超意訳

More than 5 years have passed since last update.

以下のスライドを意訳したものです。Compress周りについては触れていません。「いやいや、最新の書き方だともっと良い書き方があるんだよ!」という方のコメントをお待ちしております!
http://www.slideshare.net/paul.irish/perfcompression

クエリをキャッシュする

// 悪い例
var id = $("#content").data("id");
var itemId = $("#content").data("item-id");

// 良い例
var content = $("#content")
var id = content.data("id");
var itemId = content.data("item-id");

HTMLを生成するときにjQueryオブジェクトにアクセスし続けない

// 悪い例
$.each(reallyLongArray, function(count, item) {
  var newLi = '<li>' + item + '</li>';
  $('#ballers').append(newLi);
});

// 良い例 : DocumentFragmentを使用
var frag = document.createDocumentFragment();
$.each(reallyLongArray, function(count, item) {
  var newLi = '<li>' + item + '</li>';
  frag.appendChild(newLi[0]);
});
$('#ballers')[0].appendChild(frag);

// 良い例 : Stringを使用
var myhtml = "";
$.each(reallyLongArray, function(count, item) {
  myhtml += '<li>' + item + '</li>';
});
$('#ballers').html(myhtml);

Keep things DRY

// 悪い例
if ($ventfade.data('currently') != 'showing') {
  $ventfade.stop();
}
if ($venthover.data('currently') != 'showing') {
  $venthover.stop();
}
if ($spans.data('currently') != 'showing') {
  $spans.stop();
}

// 良い例
var elems = [$ventfade, $venthover, $spans];
$.each(elems, function(k, v){
  if (v.data('currently') != 'showing') {
    v.stop();
  }
});

アンチパターン:オブジェクトリテラルを使わない宣言

無名関数で定義されているせいで、どこで何が起こっているのか判断がつかなくなってしまうケース。

$(document).ready(function() {
  ...
  $('#magic').click(function(e) {
    $('#yayeffects').slideUp(function() {
      ...
    });
  });
  $('#happiness').load(url + ' #unicorns', function() {
    ...
  });
});

オブジェクトリテラルを使用して記述するようにする。

var PI = {
  onReady: function() {
    ...
    $('#magic').click(PI.candyMtn);
    $('#happiness').load(url + ' #unicorns', PI.unicornCb);
  },
  candyMtn: function(e) {
    $('#yayeffects').slideUp(PI.slideCb);
  },
  slideCb: function() {
    ...
  },
  unicornCb: function() {
    ...
  }
};

オブジェクトリテラルを使用することで、下記の利点を得られる。

  • コードの見通しがよくなる。
  • プロファイラで関数名を参照できる。
  • 各関数をコンソールで実行してみることができる。
  • 無名関数のときと比べて、テストが書きやすくなる。

アンチパターン:再クエリ

// create and append your element
$(document.body).append('<div class="baaron" />');
// requery to bind stuff
$("div.baaron").click(function(){  });

// better
// swap to appendTo to hold your elem
$('<div class="baaron" />')
  .appendTo(document.body)
  .click(function(){  });

$('#whats .the', context)

// パフォーマンスはこっちよりも
var arms = $('div.robotarm', '#container');
// こっちの方がいい
var arms = $('#container').find('div.robotarm');

// 読みやすさ的にはcontext?好みの問題かも。。

セレクタのパフォーマンス最適化

一番パフォーマンスが良いのは#idから下降する書き方。

// 普通の書き方
var arms = $('#container div.robotarm');
// もっと良い書き方
var arms = $('#container').find('div.robotarm');

不必要なセレクタを挟まないほうが、より高速にヒットする。

// 余計なものが混じっている
.data table.attendees td.gonzalez
// 中間をはぶこう
.data td.gonzalez

ユニバーサルセレクタはパフォーマンスを劣化させる。明示的に書いていなくても、暗黙のユニバーサルセレクタが使われている場合があるので、注意すること。

$('.buttons > *') // 超コストがかかる
$('.buttons').children() // 良い例

$('.gender :radio') // 暗黙のユニバーサルセレクタが含まれている
$('.gender *:radio') // 上記と同じ意味になる
$('.gender input:radio') // 良い例

効率的なCSSの書き方(https://developer.mozilla.org/ja/Writing_Efficient_CSS)

イベントのデリゲート

live()を使うより、delegate()を使うことでより高速化できる。

// 汚い書き方。。
$('a.trigger', $('#container')[0]).live('click', handerFn);

// 良い書き方
$('#container').delegate('click', 'a.trigger', handlerFn);

DOMの操作は総じて重い

タグのスタイル属性を直接操作するのはもってのほか。スタイルをいじりたい場合はクラスを変えよう。(DOMの操作は最小限におさえるのが原則)

ブラックボックスとしてjQueryを扱わない

単にjQueryを隠蔽する書き方は、単に可読性を下げるだけだ。

// これでは単にjQueryを隠蔽しているだけで、無駄にメソッドを増やしていだけに過ぎない。。
getScript: function( url, callback ) {
  return jQuery.get( url, null, callback, "script" );
},
getJSON: function( url, data, callback ) {
  return jQuery.get( url, data, callback, "json");
},

よく使うメソッドは覚えておこう。

map(), slice(), stop(), (de)queue(), prevAll(), pushStack(), inArray(), etc…

// index() in jQuery <= 1.3.2
$('#rdworth').parent().children().index( $('#rdworth')[0] )

// prevAll()を使うと10%速くなる
$('#rdworth').prevAll().length

// jQuery1.4からはこう書ける
$('#rdworth').index()

存在しない要素に対するアクションを書かないこと

jQueryは凄く空気を読んでくれるので、そんなコードを書いたとしてもエラーは出さない・・・けど、ものすごいオーバーヘッドが裏で生じることになる。

$('#doesntexist').slideUp()
// genFx(), speed(), animate()といったメソッドが実行されるが、要素は存在しないため画面上では何の動きもあらわれない

便利なメソッド

eq(), first(), last()

var lastelem = $elems.eq(-1); // get()と同じ

$('#nav li:first') === $('#nav li').first();
$('#nav li:last') === $('#nav li').last();

data()

// 普通の書き方
$(elem).data(key, value);

// 10倍速い!
$.data(elem, key, value);
309
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
mah_lab
最近Elmにハマっています。仕事ではRuby on Railsを10年近く触ってます。 お便りはTwitterからお願いします: https://twitter.com/mah_lab
sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
309
Help us understand the problem. What is going on with this article?