Javascript classList.remove()比className字符串操作更糟糕

Javascript classList.remove()比className字符串操作更糟糕,javascript,browser,Javascript,Browser,用于从元素中删除类 elem.classList.remove("test"); 似乎表现不如 var removeCssClass = function(elem, cName) { var a = " " + elem.className + " ", b = a.indexOf(" " + cName + " "); if (b >= 0) {

用于从元素中删除类

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");
快速工作台

在Chromium和Firefox上,我发现字符串操作版本更快。考虑到
classList.add()
elem.className+=“someClass”
快得多,我有点惊讶。我意识到我对正在进行的抽象没有真正的理解

动态令牌列表实现:

Firefox DOMTokenList实现:

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

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


我怎样才能看一看引擎盖下面的情况,从而更好地了解正在发生的事情?

请记住,您的测试并不等同

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

请记住,您的测试并不等同

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

“我怎样才能在引擎盖下看一看”-你想挖多深?你已经有了源代码。你的测试有缺陷
RemovecsClass
不设置任何内容,它在
indexOf
行停止。如果在每次迭代后添加
测试
类,这两个类都将以相同的速度执行(在我的FF上,类列表甚至要快一点)。在这种情况下,问这个问题所花费的时间不是比从“更优化”的代码中节省的时间要多得多吗?当然,我运行了测试-它说
.remove()
慢了17%。它仍然估计每秒有超过200万次的操作。您是否处于每秒执行数百万次类删除的情况下,并且需要优化每次所需的微秒分数?甚至在冒险说这个比较有缺陷之前。只有当没有任何东西可以删除时,它才会更快。@Andreas-我已经找到了DOMTokenList的源代码,是的。但是JS代码调用“.classList.remove()”和执行此代码之间存在抽象关系。@kaido我知道。我没有抓住这个具体的例子。我已经测试了各种变体,对于我的机器,
removeCssClass
的性能更好。我意识到我的“基准”没有多大价值——我只是对如何更深入地了解正在发生的事情产生了兴趣。“我如何才能深入了解情况”——你想挖掘多深?你已经有了源代码。你的测试有缺陷
RemovecsClass
不设置任何内容,它在
indexOf
行停止。如果在每次迭代后添加
测试
类,这两个类都将以相同的速度执行(在我的FF上,类列表甚至要快一点)。在这种情况下,问这个问题所花费的时间不是比从“更优化”的代码中节省的时间要多得多吗?当然,我运行了测试-它说
.remove()
慢了17%。它仍然估计每秒有超过200万次的操作。您是否处于每秒执行数百万次类删除的情况下,并且需要优化每次所需的微秒分数?甚至在冒险说这个比较有缺陷之前。只有当没有任何东西可以删除时,它才会更快。@Andreas-我已经找到了DOMTokenList的源代码,是的。但是JS代码调用“.classList.remove()”和执行此代码之间存在抽象关系。@kaido我知道。我没有抓住这个具体的例子。我已经测试了各种变体,对于我的机器,
removeCssClass
的性能更好。我意识到我的“基准”没有多大价值——我只是对如何更深入地理解正在发生的事情感兴趣。此外,正如Kaido提到的,测试实际上并没有删除一个类。两者都试图删除一个不存在的类,所以这个测试告诉我们哪个noop更快。请参阅上面的注释。我的沟通能力差。这些“基准”实际上毫无意义,因为它们被用来决定在所有情况下是否使用一种方法而不是另一种方法,而且在任何情况下,性能都不重要。我的目的是给出一个示例/上下文,说明我对如何更好地理解浏览器JS代码产生了兴趣(没有充分的理由)——我想所有这些都必须是JIT的,并由(例如)v8执行,但必须有某种互操作层调用我链接的本机代码。我的目标是学习,而不是性能优势。此外,正如Kaido提到的,测试实际上并没有删除一个类。两者都试图删除一个不存在的类,所以这个测试告诉我们哪个noop更快。请参阅上面的注释。我的沟通能力差。这些“基准”确实有意义