【问题标题】:JavaScript - === vs == operators performanceJavaScript - === vs == 运算符性能
【发布时间】:2012-09-04 16:26:04
【问题描述】:

几周前,我在C 中阅读了关于比较运算符的主题Is < faster than <=?。据说&lt;&lt;= 之间的性能没有区别,因为它们被解释为相同/相似的机器命令。

同时,在我们公司的“最佳实践”中,有人说我们应该始终使用“===”来比较事物,而不是“==”。所以,我开始怀疑这是否总是合适的,因为我习惯使用“==”和“typeof ... ==”并且不想改变我的写作方式:-]

请注意,这是在 JavaScript 的上下文中。

所以,我有一点研究,这里Which equals operator (== vs ===) should be used in JavaScript comparisons?据说:

这是因为相等运算符 == 确实类型强制...意思 解释器隐式尝试转换值,然后 进行比较。

另一方面,身份运算符 === 不做类型 强制,因此它不会转换值的值 比较时

我开始怀疑这是否意味着当我使用“===”运算符时,我将获得良好的性能,因为不会花费任何资源来转换操作数。而在所有的代码都变成了机器命令之后,这是否意味着就像C在使用&lt;&lt;=时没有区别一样,在JavaScript和其他语言中也是一样的?

【问题讨论】:

  • 通向地狱的道路由微优化铺平。
  • “毕竟编码都变成了机器指令” 但是不同语言中的每一条相同的指令不一定都会变成相同的机器码。
  • 试试看这篇文章:stackoverflow.com/questions/8044750/…
  • 您希望比较运算符执行类型强制吗?不?然后使用===。我在这里看不到选择。
  • 值得一提的是,在 2017 年,=== 比 V8 中的 == 更快,当编译器可以通过执行分析证明类型相同时 - 代码的后续运行可以在 === 中使用快捷方式他们不能在==。这是实现细节,可能会改变 - 使用正确的运算符。

标签: javascript performance equality comparison-operators equality-operator


【解决方案1】:

首先,性能根本不是问题。对于任何实际脚本,与代码中的其他瓶颈(通常 DOM 操作将是第一目标)相比,使用一个运算符相对于另一个运算符的任何性能提升都将非常小。

其次,在许多情况下,===== 将执行完全相同的步骤。当两个操作数的类型相同时(例如,两个字符串或两个数字),ECMAScript 规范对两个运算符的步骤完全相同。因此,如果您在一个浏览器或其他环境中观察到相同类型的操作数的两个运算符之间的性能差异,则既不能保证也不太可能在另一个浏览器中看到类似的差异。

typeof 的情况下,正如你的问题中提到的,两个操作数保证是相同的类型(字符串),并且两个运算符将做完全相同的事情,所以唯一支持的理由一个运算符优于另一个运算符

整个 JS 社区对此采取了相当强硬的态度:共识似乎是“除非你需要类型强制,否则永远不要使用 ==!=”,这对我的口味来说太教条了。

【讨论】:

  • 很多时候,我都收到了来自服务器的大量数据。想象一千行,这一行中的每个值都应该与其他值进行比较。如果信息以字符串形式返回,并且我将其与“==”进行比较,因为它毕竟是一个“数字”,这意味着 1000 次隐蔽操作。这就是为什么我认为性能很重要。
  • @Joro:我不确定我是否理解你的观点。如果您的操作数属于不同类型,那么 ===== 将有不同的行为,因此别无选择:您必须使用能够进行所需比较的那个。
  • 我明白你的意思。我想说的是,你必须为任何情况做好准备。返回记录可能是字符串格式,但经过一段时间和服务器函数更新,然后返回像数字一样。所以,我认为更好的解决方案是使用“==”,因为我不会被返回数据格式所依赖。
  • 这不是一个好的答案:不说什么更快,不引用任何证据(没有基准),只有正式的规范,即不是该语言的真正实现。
  • @PeterKrauss:我强烈反对。语言规范规定了实现必须如何工作。显示少数实现今天如何执行的基准测试几乎不会告诉您明天的实现将如何执行:在比较相同类型的操作数时,===== 之间有显着差异的实现出错了,很可能将在未来的版本中修复。正如答案中提到的,我还认为,在几乎所有情况下,担心任何潜在差异都是毫无意义的。
【解决方案2】:

我觉得最好用易于验证的证据来回答。

这些操作非常小,很难对其进行性能测试。

  • == 1648 正确
  • === 1629 正确
  • 对照测试 1575 正确

如果你减去控制测试,看起来它们在我的浏览器上的速度有大约 30% 的差异。如果您多次这样做,您可能会得到不同的答案,但 === 通常会出现最快,我认为这只是证明差异是多么微不足道。

我认为这几乎证明了其他人所说的,性能差异是浪费时间去思考,但它也表明 === 实际上更快。希望这个答案可以节省其他人的时间,那些必须看到证据的人。

2019 年更新

2019-04-09 Firefox 改进测试:

  • == 1383 正确
  • === 1167 正确
  • 对照测试 429 正确

2019-04-09 Chrome 改进测试:

  • == 249 正确
  • === 248 正确
  • 对照测试 248 正确

2019-04-09 改进测试的 Edge:

  • == 22510 正确
  • === 20315 正确
  • 对照测试 4968 正确

这些年来,浏览器变得越来越智能,看来我最初的测试已经与 Chrome 和 Firefox 中的酷优化相悖,使其不再有用。我使测试更难优化,并增加了运行次数以再次获得有意义的结果。 看起来 === 仍然更快。担心这可能仍然是浪费时间。

var testString = "42";
var testString2 = "43";
var testString3 = "42";
var testNumber = 42;
var testNumber2 = 43;
var testNumber3 = 42;

var testObject = {};
var testObject2 = {};
var testObject3 = testObject;


var start = Date.now();
var result = null;
for(var i = 0; i < 200000000; i++){
	result = 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3
}

console.log("==", Date.now() - start, result);

var start = Date.now();
var result = null;
for(var i = 0; i < 200000000; i++){
	result =
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3
}
console.log("===", Date.now() - start, result);
var start = Date.now();
var alwaysTrue = true;
var alwaysFalse = false;
for(var i = 0; i < 200000000; i++){
	result = 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue
}
console.log("control test", Date.now() - start, result);

【讨论】:

  • 在我的浏览器 (Firefox) 上运行,值是 == 1062=== 283... 但“控制测试 283”也是 283 (!)...嗯,“=== "通过解释测试非常快。 问题:用 Chrome 进行测试,结果是相反的 (!)。 "== 387" "=== 352", "control test 350"... 或 NodeJS (node v11.9.0) 并使用现代的console.time() console.timeEnd(),类似于=== 300ms== 200ms 和@987654329 @(或运行 10000000000 个循环 ===29800ms,==20040 和 nop 20045ms),“==”接近于零。 ...好吧,我更改了代码以避免编译器优化,但问题仍然存在...
  • 嗨 @TimDown 和 Rick,您可以确认 === 在 Firefox 中更快 here in this other question... 但它不是通常的性能检查,它是衡量现实,一种检查编译器(平均而言)执行 ECMA 262 规定的方法。
【解决方案3】:

对于 js,如果在字符串类型上使用 === 运算符并且字符串是完全相同的字符,则该运算符将返回 true。对于对象,它比较对象引用,而不是内容。

来自ECMA standard

11.9.6 严格等式比较算法 比较 x === y,其中 x 和 y 是值,产生真或假。这样的比较 执行如下:

  1. 如果 Type(x) 与 Type(y) 不同,则返回 false。
  2. 如果 Type(x) 未定义,则返回 true。
  3. 如果 Type(x) 为 Null,则返回 true。
  4. 如果类型(x)是数字,那么 一种。如果 x 是 NaN,则返回 false。 湾。如果 y 是 NaN,则返回 false。 C。如果 x 与 y 的数值相同,则返回 true。 d。如果 x 为 +0 且 y 为 -0,则返回 true。 e.如果 x 为 -0 且 y 为 +0,则返回 true。 F。返回 false。
  5. 如果 Type(x) 是字符串,那么如果 x 和 y 是完全相同的字符序列(相同长度和相同的字符在 对应位置);否则,返回 false。
  6. 如果 Type(x) 是布尔值,如果 x 和 y 都为真或都为假,则返回真;

【讨论】:

  • 这包含了一些错误的信息(而且这个小小的编辑太多是事后的想法)。不要求str === str 仅对同一对象为真。 "a" + "b" === "ab" 为真,但不要求 "a" + "b""ab" 被实习到同一对象。虽然 both ===== 如果 implementation 确定两者都是相同的对象值,则可以“提前停止”(这将是一个特定于实现的优化,它将在一些情况下工作),否则字符串值必须逐个字符地与===进行比较。
  • 所以,毕竟,这个示例等号背后有很多逻辑:-] ...感谢您的回答和 ESMA 书籍链接 - 我觉得这很有趣。
  • 第一段几乎完全不正确。如果您有兴趣,我可以提供详细的解释。 (您是否一直在考虑使用不同的语言来写 whit?)
  • @ŠimeVidas 这将是有用和有趣的。我也使用其他语言 - C/C++/Java/ruby on rails
  • @Joro 运算符 ===== 仅在操作数的类型不同(例如 StringNumber)时有所不同。如果比较两个 Object 值,它们的行为相同 - obj1 == obj2 等效于 obj1 === obj2。其他类型也是如此 - str1 == str2 等价于 str1 === str2 等。这就是第一段出错的原因(至少在 JavaScript 的上下文中)。
【解决方案4】:

这是一种脚本语言。这些运算符的性能不应该那么重要,您应该担心它,因为还有许多其他消耗更多功率的东西,例如它在虚拟机中运行的事实,是弱类型,在浏览器中使用 HTML DOM...

此外,两个运算符做的事情完全不同,所以一个可能在任何情况下都不能与另一个互换。

也就是说,我认为(但尚未测试)=== 更快。原因是,它只需要比较类型,如果匹配,则比较原始数据。如果它们不匹配,== 运算符将尝试将一种类型转换为另一种类型。在大多数情况下,这将是一项更昂贵的操作。

这是幸运的,因为在大多数情况下=== 是更好的选择。 :)

但无论如何,您可以轻松测试它(确保您测试多个案例,包括相同类型和几个不同类型),但如果您不知道如何测试它,我会停止担心共。差异,如果有的话,不会杀死你。

【讨论】:

  • 虽然通用,就像大多数这些答案 wrt ===== “性能”一样,我怀疑 ===== 的实际速度会受到所提供值的影响。虽然== 规则“看起来更长”或“需要更多操作”,但应该认为===== 的“超级匹配”,因此始终可以尝试=== 规则并停止如果== 规则之前有匹配项。当然,这最终将取决于许多其他因素,其中最重要的是实施
  • @pst,这是正确的,但如果速度如此重要以至于您必须使用此类双重检查,您可能需要考虑使用与 Javascript 不同的语言。此外,如果您对类型很严格(变量可以是整数或未赋值,但绝不是字符串),您可以安全地使用严格比较运算符。即使在需要== 的情况下,您也可以先执行类型转换。我认为这使您的代码更具可读性和“更安全”,这对我来说比速度更重要。
【解决方案5】:

性能差异可以忽略不计,这意味着您不应该浪费宝贵的大脑周期来思考它。如果你真的想知道,你应该测试。

使用===,除非你有充分的理由不这样做(你可能不这样做)。

【讨论】:

    【解决方案6】:

    无论您获得何种性能,=== 在这种情况下显然是更好的选择。诸如更好的性能之类的其他任何事情都只是锦上添花。此外,这两种方式的差异很小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 2013-10-19
      • 2018-02-16
      • 1970-01-01
      • 2013-07-15
      • 1970-01-01
      相关资源
      最近更新 更多