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');
Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
Muleskinner
  • 14,150
  • 19
  • 58
  • 79
  • 12
    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 classes – Samich Sep 13 '11 at 14:27
  • 7
    Just add the class without testing. If it already exists, it won't be added again. – Blazemonger Sep 13 '11 at 14:27

4 Answers4

191

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.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
jmar777
  • 38,796
  • 11
  • 66
  • 64
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 ] + " ";
}
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • 2
    Please re-read my question and you will notice that its not about beeing safe but about best practice – Muleskinner Sep 13 '11 at 14:33
  • 7
    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 / thanks – Muleskinner Sep 13 '11 at 14:44
  • 5
    @Muleskinner that's what I was implying. – Raynos Sep 13 '11 at 15:56
  • 42
    @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. – eirirlar Feb 28 '13 at 08:36
  • This is OK, but really too complicated and not needed at all. The other answer should've been accepted. – MightyPork Sep 29 '14 at 19:51
  • 10
    There's far too much attitude in this answer. Could have answered it with some tact. – dreadwail Feb 15 '15 at 20:51
  • 2
    @Raynos **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. – trss Aug 11 '15 at 14:54
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.

Community
  • 1
  • 1
Igwe Kalu
  • 14,286
  • 2
  • 29
  • 39
1
$("label")
  .not(".foo")
  .addClass("foo");