web-dev-qa-db-ja.com

追加する前にクラスが既に割り当てられているかどうかを確認してください

JQueryでは、クラスを追加する前に、クラスが既に要素に割り当てられているかどうかを確認することをお勧めしますか?それはまったく効果がありますか?

例えば:

<label class='foo'>bar</label>

クラスbazが既にlabelに割り当てられている場合、これが最良のアプローチでしょうか?

var class = 'baz';
if (!$('label').hasClass(class)) {
  $('label').addClass(class);
}

またはこれで十分でしょうか:

$('label').addClass('baz');
105
Muleskinner

addClass()を呼び出すだけです。 jQueryがチェックを行います。自分でチェックすると、jQueryがstillを実行するため、作業が2倍になります。

170
jmar777

コンソールでの簡単なチェックでは、同じクラスでaddClassを複数回呼び出すことは安全であることがわかります。

具体的には、 ソース でチェックを見つけることができます

if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
  setClass += classNames[ c ] + " ";
}
46
Raynos

この質問は、 これと重複するものとしてマークされた別の に続いて私の注意を引きました。

この回答では、受け入れられた回答を要約し、詳細を少し追加しています。

不要なチェックを回避することで最適化を試みています。この点に注意する必要がある要素は次のとおりです。

  1. javaScriptを介してDOM要素を操作することにより、クラス属性に重複したクラス名を含めることはできません。 HTMLに_class="collapse"_がある場合、Element.classList.add("collapse");を呼び出しても、追加のcollapseクラスは追加されません。基礎となる実装はわかりませんが、それで十分だと思います。
  2. JQueryは、そのaddClassおよびremoveClass実装で必要なチェックを行います( source code )。 addClassの場合、いくつかのチェックを行った後、クラスが存在する場合、JQueryは再度追加しようとしません。 removeClassについても同様に、JQueryはcur.replace( " " + clazz + " ", " " );の行に沿って何かを実行し、クラスが存在する場合にのみクラスを削除します。

重要なことに、JQueryは無意味な再レンダリングを回避するために、removeClass実装でいくつかの最適化を行います。こんなふうになります

_...
// only assign if different to avoid unneeded rendering.
finalValue = value ? jQuery.trim( cur ) : "";
if ( elem.className !== finalValue ) {
    elem.className = finalValue;
}
...
_

したがって、あなたができる最適なmicro最適化は、関数呼び出しのオーバーヘッドと関連する実装チェックを回避することを目的とするでしょう。

クラスの追加または削除のタイミングを完全に制御し、collapseクラスが最初に存在しない場合は、collapseという名前のクラスを切り替えたい場合、次のように最適化できます。 :

_$(document).on("scroll", (function () {
    // hold state with this field
    var collapsed = false;

    return function () {
        var scrollTop, shouldCollapse;

        scrollTop = $(this).scrollTop();
        shouldCollapse = scrollTop > 50;

        if (shouldCollapse && !collapsed) {
            $("nav .branding").addClass("collapse");
            collapsed = true;

            return;
        }

        if (!shouldCollapse && collapsed) {
            $("nav .branding").removeClass("collapse");
            collapsed = false;
        }
    };
})());
_

余談ですが、スクロール位置の変更のためにクラスを切り替える場合は、スクロールイベントの処理を throttle にすることを強くお勧めします。

4
Igwe Kalu
$("label")
  .not(".foo")
  .addClass("foo");