Check if class already assigned before adding
Asked Answered
H

4

122

In jQuery, is it recommended to check if a class is already assigned to an element before adding that class? Will it even have any effect at all?

For example:

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

When in doubt if class baz has already been assigned to label, would this be the best approach:

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

or would this be enough:

$('label').addClass('baz');
Halie answered 13/9, 2011 at 14:24 Comment(2)
I used .hasClass only when I need to check if class exists, if I just need to assign class - I use .addClass. jQuery doesn't duplicate the classesAnd
Just add the class without testing. If it already exists, it won't be added again.Rhythmist
P
193

Just call addClass(). jQuery will do the check for you. If you check on your own, you are doubling the work, since jQuery will still run the check for you.

Postlude answered 13/9, 2011 at 14:27 Comment(0)
S
48

A simple check in the console would have told you that calling addClass multiple times with the same class is safe.

Specifically you can find the check in the source

if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
  setClass += classNames[ c ] + " ";
}
Swirsky answered 13/9, 2011 at 14:27 Comment(7)
Please re-read my question and you will notice that its not about beeing safe but about best practiceHalie
From your edited answer I see that jQuery actually check if the class allready is assigned before adding it, i.e. it would be bad practice to do the check yourself / thanksHalie
@Halie that's what I was implying.Swirsky
@Raynos: A simple check in the console would have told you that calling addClass multiple times with the same class is safe. Still, this question was one of the top hits when I Googled for an answer... Even trivial stuff that is well documented elsewhere has imho a place on Stack Overflow.Ptolemaist
This is OK, but really too complicated and not needed at all. The other answer should've been accepted.Lenity
There's far too much attitude in this answer. Could have answered it with some tact.Chromatography
@Swirsky A simple check in the console !== documentation by any measure. It may vary from browser to browser. However, the source is a much better option to rely upon. Thank you for that.Phonology
C
5

This question got my attention following another which was marked as a duplicate of this one.

This answer summarises the accepted answer with a little added detail.

You're trying to optimise by avoiding an unnecessary check, in this regard here are factors you must be aware of:

  1. it's not possible to have duplicate class names in the class attribute by means of manipulating a DOM element via JavaScript. If you have class="collapse" in your HTML, calling Element.classList.add("collapse"); will not add an additional collapse class. I don't know the underlying implementation, but I suppose it should be good enough.
  2. JQuery makes some necessary checks in its addClass and removeClass implementations (I checked the source code). For addClass, after making some checks and if a class exists JQuery doesn't try to add it again. Similarly for removeClass, JQuery does somethings along the line of cur.replace( " " + clazz + " ", " " ); which will remove a class only if it exists.

Worth noting, JQuery does some optimisation in its removeClass implementation in order to avoid a pointless re-rendering. It goes like this

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

So the best micro optimisation you could do would be with the aim of avoiding function call overheads and the associated implementation checks.

Say you want to toggle a class named collapse, if you are totally in control of when the class is added or removed, and if the collapse class is initially absent, then you may optimise as follows:

$(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;
        }
    };
})());

As an aside, if you're toggling a class due to changes in scroll position, you are highly recommended to throttle the scroll event handling.

Conyers answered 24/8, 2015 at 13:16 Comment(0)
N
1
$("label")
  .not(".foo")
  .addClass("foo");
Nashbar answered 28/11, 2018 at 6:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.