为什么对象引用相等不比字符串相等快得多?

时间:2018-10-28 19:17:07

标签: javascript performance

只要有选项卡开关或类似的结构,我就会看到这种模式:

const tabs = {
  FIRST: 'FIRST',
  SECOND: 'SECOND',
}

const getActiveClassName = current => activeTab === current ? 'active' : ''

...

const activeTab = tabs.FIRST

<button className={getActiveClassName(tabs.FIRST)}/>
<button className={getActiveClassName(tabs.SECOND)}/>

我认为“字符串比较”中的逐字母处理必须效率低下,因此我编写了一个测试并将其与“对象相等性”进行比较,希望比较引用会更快:

const tabs = {
  FIRST: {},
  SECOND: {},
}
  

结果是几乎没有区别。 为什么?

enter image description here

The JSPerf test is here.

2 个答案:

答案 0 :(得分:3)

字符串比较并不总是需要一个字母一个字母地进行。

字符串不是作为原始数据值实现的(就像其他原始类型一样),而是实际上是对其(不可变的)内容的引用。这以及它们是不可变的事实,允许在您的示例中进行一些优化:

  • 两个引用相同内容存储器的字符串被认为是相等的。如果您分配activeTab = tabs.FIRST然后比较activeTab === tabs.FIRST,我敢打赌只会比较参考。
  • 两个不相等的字符串仅会进行比较,直到区分它们的第一个字母为止。比较"First" === "Second"只需访问一个字母。
  • string literals are typically interned起,当引擎知道它确实比较两个内部字符串(不是动态构建的字符串)时,只需要比较它们的引用。对实习字符串内容的两个不同引用意味着两个不同的内容,因为具有相同内容的实习字符串将共享其内存。因此,即使您的activeLongString也可以通过常量比较与longStrings中的其他常量加以区分。

答案 1 :(得分:0)

深入计算机的腹部,字符串比较依赖于C库及其strcmp(3)函数。

由于这是最常用的功能之一,因此C库开发人员已经对其进行了优化。特别是,当发现两个字符串至少相差一个字节时,可以认为这两个字符串不同并且比较短路。

对于s * hit和咯咯笑声,您实际上可能会发现x {86}在x86_64程序集的macOS(某些旧版本)中是如何实现的:

https://opensource.apple.com/source/Libc/Libc-825.26/x86_64/string/strcmp.s.auto.html

但是请注意两件事:

  1. 这些类型的东西都接近金属,而JS则不然
  2. 字符串比较实现之类的东西取决于操作系统

因此,您注定会得到奇怪的结果,因为效果是如此之小,并且取决于下一个操作系统的版本。请注意,JS运行时必须经历很多麻烦才能进行字符串比较,并且相关的噪音完全使比较运算符本身的成本黯然失色。

我对所有JS开发人员的建议是仅专注于代码正确性和UX。