双等号 (==) 和三等号 (===) 之间的 JavaScript 性能差异

Posted

技术标签:

【中文标题】双等号 (==) 和三等号 (===) 之间的 JavaScript 性能差异【英文标题】:JavaScript performance difference between double equals (==) and triple equals (===) 【发布时间】:2011-12-24 02:10:33 【问题描述】:

javascript 中,使用双等号 (==) 与使用三等号 (===) 之间是否存在性能差异?

示例:if (foo == bar)if (foo === bar)

【问题讨论】:

您永远不会注意到任何事情。继续前进。 它们有不同的用途,“更高的性能”不是其中之一。这不是问题,当您想获得它们提供的功能时使用它们。 推荐阅读:You don't know JS 由于这仍然是该问题的最高 Google 结果,并且我没有看到任何测试结果,所以我将添加一个。一个小 Node.js 测试的平均结果,运行 4 次(2 个操作符中的每一个总共测试 80,000,000,000 次),发现 ===== 快 0.0027%。差异,如果它真的那么高,大约比眨眼或人类大脑对平均刺激做出反应的时间快 10,000 倍。为了支持Lightness Races in Orbit 的评论,我想不出人类可能会注意到两者之间的速度差异的场景。 @JonSurrell 感谢您提供有趣的链接 :) 五年后,the address has changed 【参考方案1】:

如果比较的类型相同,它们是相同的。也就是说,他们使用完全相同的算法

如果类型不同,则性能无关紧要。要么你需要类型强制,要么你不需要。如果您不需要它,请不要使用==,因为您得到的结果可能会出乎意料。

【讨论】:

【参考方案2】:

严格比较 (===) 总是会稍微快一些,但 the difference is usually negligible。

如果您确定在比较中不需要类型强制,那么首选=== 绝对是有意义的。它总是至少和==一样快。

【讨论】:

很有趣,因为== 对我来说击败了===,这两次我都在FF7 上进行了测试。我同意=== 应该更快,但测试声称并非如此。 (可能是 Javascript 引擎/CPU 负载的差异,谁知道) @Nightfirecat:这很有趣。你是在比较变量还是文字? 我只是使用它使用的默认测试——即“==/=== 仅在相同类型上”测试,因为这些测试是其中最快的。我相信与常规比较测试相反,所有按类型比较中都出现了相同的模式,不记得了。 如果操作数属于同一类型,则指定 ===== 以执行完全相同的步骤。 console.time("test") 2 === 2 console.timeEnd("test") VM137:3 test: 0.006103515625ms console.time("test1") 2 == 2 控制台。 timeEnd("test1") VM147:3 test1: 0.0048828125ms 我知道 === 稍快我如何测试这个为什么我得到相反的结果是我的方法是错误的?【参考方案3】:

编辑:供参考,这是 Axel Rauschmayer 博士的规范解释 http://www.2ality.com/2011/06/javascript-equality.html 写得真好。

===(严格相等):仅考虑具有相同类型的相等值。

    未定义 === 未定义,空 === 空, NaN === 没有,包括它自己, 原始 [Number|String|Boolean] === 原始值相等, 对自己 (+0 === -0) 两个对象 [Array|Object|Function] === 只有自己(完全相同的实体)

==(宽大平等)

    如果两个值的类型相同:与 === 比较。 未定义 == 空 数字和字符串:字符串 => 数字和比较 boolean and non-boolean => non-boolean to number and compare 字符串或数字 => 对象:将对象转换为原始对象并进行比较。

在所有现代 Javascript 环境中,它们的实现方式完全不同。简单来说,== 通过将给定变量转换为原语(字符串、数字、布尔值)来测试相似性。 === 测试严格相同,这意味着完全相同的 Object 或原始值,无需转换。

如果你这样做 objOne == objTwo 实际发生的是 [[EQUALS]].call(objOne.valueOf(), objTwo.valueOf())

valueOf 的解析可能有点牵扯,在 JS 中公开的函数和内部引擎的东西之间来回切换。可以说,比较总是会以两个强制为原始值的值结束,否则会引发错误。

编辑: EQUALS 实际上会先尝试 STRICT_EQUALS,它会抢占进程的其余部分。

这里有趣的一点是 valueOf(及其伙伴 toString)是可覆盖的。在 Chrome 中运行这段代码(我认为任何 webkit,不确定 JSC 和 V8 是否共享这个花絮)。它会让你大吃一惊:

var actions = [];
var overload = 
  valueOf: function()
    var caller = arguments.callee.caller;
    actions.push(
      operation: caller.name,
      left: caller.arguments[0] === this ? "unknown" : this,
      right: caller.arguments[0]
    );
    return Object.prototype.toString.call(this);
  
;
overload.toString = overload.valueOf;
overload == 10;
overload === 10;
overload * 10;
10 / overload;
overload in window;
-overload;
+overload;
overload < 5;
overload > 5;
[][overload];
overload == overload;
console.log(actions);

输出:

[  operation: 'EQUALS',
    left: overload,
    right: 10 ,
   operation: 'MUL',
    left: overload,
    right: 10 ,
   operation: 'DIV',
    left: 'unknown',
    right: overload ,
   operation: 'IN',
    left: overload,
    right: DOMWindow ,
   operation: 'UNARY_MINUS',
    left: overload,
    right: undefined ,
   operation: 'TO_NUMBER',
    left: overload,
    right: undefined ,
   operation: 'COMPARE',
    left: overload,
    right: 5 ,
   operation: 'COMPARE',
    left: 'unknown',
    right: overload ,
   operation: 'ToString',
    left: 'unknown',
    right: overload  ]

===== 之间区别的本质是 === 没有出现在该列表中。它完全跳过了进入 JavascriptLand 的旅程。比较性能时,这种冒险是昂贵的。

但是,您需要考虑引擎优化。对于大多数对象,引擎将能够减少大部分步骤并留在 NativeLand 中并获得几乎相同的性能。但这并不是保证,如果有什么东西阻止引擎使用优化、代码中的一些花哨或覆盖内置函数或无数问题,那么您会立即看到性能结果。 === 强制它。

=== 几乎是 Javascript 中唯一不可变的东西。

【讨论】:

你的证据在哪里?由于 ===== 被指定为在操作数属于同一类型时完全相同地工作,我无法相信 JS 环境在这种情况下会以不同的方式实现它们。 ....你在第一句话之后读过我的任何帖子吗?我确实包含了 V8 输出。简短的回答: == 首先调用 === 并且在 === 为真的情况下,差异可以忽略不计。除此之外 == 根据定义必须输。 只是为了后代注意。我的上述证据是我想出的一种新方法,它能够在所有当前使用 V8 或 JavaScriptCore 的实现中,从任意 JavaScript 对象中识别内部 JS 引擎操作符函数调用者和正确定位的操作数,这是我在其他地方从未见过的,并且直接启用了 JS 中的运算符重载,否则这是不可能的,目前还没有成功实现。 我读过。抱歉,我应该更具体地说明缺少哪些证据:关于“所有现代 Javascript 环境”的部分。暴露出来的 V8 内部结构很有趣,但 valueOf() 自 1997 年 ECMAScript 1 以来就已经存在,因此并不新鲜。您还没有解决我的观点,即当两个操作数属于同一类型时会发生什么的问题。将operator == operator === 添加到您的示例中,您会看到它们都没有出现在您的actions 数组中。 这真的应该是答案,imo。 == 调用 === 然后尝试强制以查看它是否以其他方式相似。那么,当您尝试比较身份时,=== 对于不相等的对象显然更快。【参考方案4】:

由于性能,我认为===的性能更好,因为=====更严格,

例如在 Chrome 控制台中尝试以下操作。

> 1 == '1'
  true
> 1 === '1'
  false

== 必须检查的东西比=== 还要多

【讨论】:

【参考方案5】:

从一些脆弱的测试来看,== 似乎比=== 稍微快一些。

我的意思是,我可以在数百万次测试的交互中看到几毫秒的差异。您不可能需要性能提升,而不是使用最适合手头任务的方法。

编辑:实际上,似乎取决于您要比较的 /what/ 和浏览器实现。换句话说,不用担心。

【讨论】:

=== 在大多数情况下更快。有边缘情况(你找到了一个)。然而,从代码实践/风格指南=== 每次都能胜出 “别担心”,“你不可能需要性能提升”。你不知道这个用户的意图,以及所有来这里问这个问题的用户。 @cdosborn 哇,你好 2011。这个 Q 早于 SO 上的 nodejs 标签。是的,你是对的。当时这是一个公平的假设,这是在浏览器中,并且削减毫秒/数百万次评估将是.. 对您的时间的错误利用。大约 5 年的时间里,情况发生了很大变化。【参考方案6】:

这取决于被比较的项目。由于“===”比“==”更严格,它应该比“==”更快地返回false。但是,如果这两个项目严格相等,“===”应该比“==”花费更多的时间,因为它必须检查更多的属性是否相等。

【讨论】:

你有比较的来源吗?其他答案提到差异可以忽略不计 性能方面的差异基本上可以忽略不计,但仍然存在 请进一步解释——它为什么存在?真的可以忽略不计吗?最好根据事实写出答案,以便其他人可以从中学习

以上是关于双等号 (==) 和三等号 (===) 之间的 JavaScript 性能差异的主要内容,如果未能解决你的问题,请参考以下文章

js中两个等号(==)和三个等号(===)的区别

小程序 小知识总结

javascript双等号引起的类型转换

js—双等号引起的类型转换过程

在编程文档中,双冒号后跟等号 (::=) 是啥意思?

Java双等号,Equals(),HashCode()小结