首页 > 解决方案 > classList.remove() 比 className 字符串操作更糟糕

问题描述

为了从元素中删除一个类,

elem.classList.remove("test");

似乎表现不如

var removeCssClass = function(elem, cName) {
    var a = " " + elem.className + " ",
    b = a.indexOf(" " + cName + " ");

    if (b >= 0) {
       elem.className = (a.substr(0, b) + " " + a.substring(b + cName.length + 1, a.length)).trim()
    }
}
removeCssClass(elem, "test");

快速板凳https://jsbench.me/yhkmn56aox/1

在 Chromium 和 Firefox 上,我都知道字符串操作版本更快。考虑到这classList.add()elem.className += " someClass". 我意识到我对正在进行的抽象没有真正的理解。

Chromium DOMTokenList 实现: https ://chromium.googlesource.com/chromium/blink/+/master/Source/core/dom/DOMTokenList.cpp

Firefox DOMTokenList 实现: https ://searchfox.org/mozilla-central/source/dom/base/nsDOMTokenList.cpp

我不确定我什至会如何开始尝试理解为什么一个版本比另一个版本快。我假设 JS 字符串操作是“在 JS 内”完成的(由 v8/SpiderMonkey 执行),但最终的分配elem.className是绑定/互操作。同样,我假设elem.classList.remove()只是绑定到上述实现。

据了解,在 JS 停止执行之前,浏览器对添加/删除的类的处理/处理都不会发挥作用 - 因此,作为重新渲染过程的一部分,浏览器的任何后续处理都无法解释。(这个对吗?)

我如何才能深入了解并更好地了解正在发生的事情?

标签: javascriptbrowser

解决方案


请记住,您的测试是不等价的。

  • 不确定基准测试站点做了什么,但我认为它不会在每次测试后重新添加 HTML,所以你只是在测试每个代码的提前退出
  • 在我的机器上,使用 Firefox,我得到了classList更好的性能
  • 对于重复的类,您的代码只会删除第一个类,而.remove将删除所有类

推荐阅读