JavaScript 字符串相等性能比较

Tih*_*čić 3 javascript string

我有一个菜鸟 javascript 问题。假设我们有两个相等的非常大的字符串(约一百万个字符或更多) - 它们具有相同的长度和相同的内容。假设我们有这两个函数,它们都做同样的事情(比较字符串):

function equals1(a, b) {
    return a === b;
}

function equals2(a, b) {
    if (a.length !== b.length) {
           return false;
    }
    for (var i = 0; i < a.length; ++i) {
        if (a[i] !== b[i]) {
            return false;
         }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

为什么第一个函数 (equals1()) 的速度几乎是第二个函数的两倍?如何改进第二个,使其性能与第一个一样好?

Mic*_*dis 6

根据 ECMAScript 委员会的一位人士的说法,最有可能的 Javascript 正在执行字符串实习(Do common JavaScript implementations use string interning?)。我认为然后 === 将是 O(1) 但基于原始海报的性能测试它是 O(n) 因为将字符串加倍会使相等的时间加倍.. 没有使用字符串实习真的很遗憾他们应该是这样的。

更新:JSPerf

原始海报声称应该支持 O(N) 复杂性来自http://jsperf.com/eqauility-is-constant-time 似乎即使我有 16 倍大的字符串,时间也不会改变超过 1- 2%

所以请重新考虑我删除的那些事情和你的反对票

换句话说:

当你做

var str1 = "stringwithmillionchars"; //stored in address 51242
var str2 = "stringwithmillionchars"; //stored in address 12313
Run Code Online (Sandbox Code Playgroud)

一旦假设在内存的地址 201012 中,“stringwithmillionchars”将被存储,并且 str1 和 str2 都将“指向这个地址 201012。这个地址可以通过某种哈希确定以映射到内存中的特定位置。

所以在做的时候

"stringwithmillionchars"==="stringwithmillionchars"

看起来像

getContentOfAddress(51242)===getContentOfAddress(12313)

或者 201012 === 201012

这需要 O(1)/恒定时间

您示例中的 for 循环 (equals2()) 的时间为 O(N),其中 N 是两个字符串的长度。那是因为它必须在每对字符之间进行 N 次比较,并在 i 和 str.length 之间进行 N 次比较。

注意:地址号码是随机选择的,用于说明目的。

重要:基于我的问题中的性能比较(为什么 Javascript ===/== 字符串相等有时具有恒定的时间复杂度,有时具有线性时间复杂度)仅当字符串直接用引号分配时才会发生实习,否则比较将采用线性时间而不是常数,因为发生了字符到字符的比较。

  • 感谢您的回答,但我认为情况并非如此。我尝试将字符串的长度增加 2 倍,比较 (a === b) 需要两倍的时间(因此,它也是 O (n)) (2认同)
  • 我建议你离开它,不要在这上面浪费更多时间。你的努力是非凡的,但我认为你说到了你的观点。你的努力得到了我的 100 赏金。 (2认同)