7

I am curious if anyone knows which of these is more efficient, I am only concerned with Firefox as a browser and do not need to know that this code doesn't work in IE, etc...

Basically I am showing and hiding DOM elements based on an input field's value, an instant search if you will. I need to show or hide a "nothing found" element if no search results are shown. I am curious if it is cheaper (more efficient) to check if the "nothing found" element is in the proper state before modifying its class attribute, or to just modify the class attribute.

Question: should I remove/add the hidden class every time the function is run, even if there is no change in the element's class attribute?

if (shown_count > 0) {
    element.classList.add('hidden');
}
else {
    element.classList.remove('hidden');
}

or should I check to see if the element needs its class attribute updated before actually updating it?

if (shown_count > 0) {
    if (element.classList.contains('hidden') == false) {
         element.classList.add('hidden');
    }
}
else {
    if (element.classList.contains('hidden')) {
         element.classList.remove('hidden');
    }
}
macguru2000
  • 2,042
  • 2
  • 18
  • 27
  • 5
    Creating a benchmark with [jsperf](http://jsperf.com/) or similar would answer your question better than us, I believe. – Frédéric Hamidi Oct 17 '12 at 15:36
  • 2
    Great question. It looks like it might depend on what percentage of elements need a change on any given query. For example, if 100% need changing, the 1st is obviously more efficient. If less than 100% need changing, the answer may change. – A F Oct 17 '12 at 15:36
  • Aakil, I'm not asking about showing/hiding the actual search results, but instead I'm asking about wether I should modify one element's class attribute at the end of the function every time, or only when the class should change. – macguru2000 Oct 17 '12 at 15:43

2 Answers2

7

I think the existence check is already done by the native code, so you do not need to check it again.

So let's take a look at the source code( Note: classList is DOMTokenList object)

String DOMTokenList::addToken(const AtomicString& input, const AtomicString& token)
{
    if (input.isEmpty())
        return token;

    StringBuilder builder;
    builder.append(input);
    if (input[input.length()-1] != ' ')   // <--- check happens here
        builder.append(' ');
    builder.append(token);
    return builder.toString();
}

source comes from the WebKit's WebCore

xdazz
  • 158,678
  • 38
  • 247
  • 274
  • 2
    Any evidence or documentation to back this up? I believe you are correct...but want to make sure. Thanks – macguru2000 Oct 17 '12 at 15:38
  • 1
    I'm not sure what WebKit's source has to do with the question (which was specifically about Firefox). And even for WebKit, you're looking at the wrong function. You want `ClassList::addInternal`. But yes, the spec requires that the `add()` method on the class list check whether the class is already present before adding. So it won't double-add. – Boris Zbarsky Oct 17 '12 at 21:01
  • @BorisZbarsky I just take the WebKit's source for example, isn't `classList` in WebKit `DOMTokenList`? I got it in chrome so I thought it was `DOMTokenList`. – xdazz Oct 18 '12 at 01:19
  • The implementation is a subclass of `DOMTokenList` that overrides various methods. But the point was that the code you quoted does NOT do any sort of "token already in list" checking. That check happens in `ClasList::addInternal`. – Boris Zbarsky Oct 18 '12 at 13:00
  • Well, besides the specificity of browser and exact source code, xdazz was correct and my jsperf test shows that, check it out at http://jsperf.com/add-remove-class-performanci – macguru2000 Oct 18 '12 at 23:20
  • Interestingly enough, it looks like the opposite is now true, checking if you should change the class before changing the class at least was faster by a significant margin on Chrome 83.0.4103.10, MacOS 10.14. – macguru2000 Jun 17 '20 at 20:59
2

After running some tests on jsperf the answer is simply that the first option is quicker. Likely due to xdazz's answer, that the classList.add method does the check already.

Here is a link to the performance test: http://jsperf.com/add-remove-class-performanci

macguru2000
  • 2,042
  • 2
  • 18
  • 27