33

几周前,我读过这个线程< 比 <= 快吗?关于比较运算符C。据说它们之间的性能没有差异,<因为<=它们被解释为相同/相似的机器命令。

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

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

所以,我做了一点研究,在这里JavaScript 比较中应该使用哪个等于运算符(== vs ===)?据说:

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

另一方面,恒等运算符 === 不进行类型强制,因此在比较时它不会转换值的值

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

4

6 回答 6

23

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

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

  • == 1648 对
  • === 1629 对
  • 控制测试 1575 真

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

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

2019 年更新

2019-04-09 Firefox 改进测试:

  • == 1383 对
  • === 1167 对
  • 控制测试 429 真

2019-04-09 Chrome 改进测试:

  • == 249 对
  • === 248 对
  • 控制测试 248 真

2019-04-09 改进测试的边缘:

  • == 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);

于 2016-08-22T19:52:22.857 回答
16

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

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

在 的情况下typeof,如您的问题中所述,两个操作数保证为相同类型(字符串),并且两个运算符将做完全相同的事情,因此偏爱一个运算符而不是另一个运算符的唯一原因是 stylistic

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

于 2012-09-25T12:10:32.667 回答
3

它是一种脚本语言。这些运算符的性能不应该那么重要,你应该担心它,因为还有很多其他的东西会消耗更多的能量,比如它在虚拟机中运行、弱类型、与 HTML 一起工作。浏览器中的DOM...

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

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

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

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

于 2012-09-11T17:25:31.907 回答
3

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

于 2012-09-11T17:24:06.807 回答
2

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

===除非你有充分的理由不使用(你可能没有),否则使用。

于 2012-09-11T17:24:39.253 回答
-4

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

ECMA标准

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

  1. 如果 Type(x) 与 Type(y) 不同,则返回 false。
  2. 如果 Type(x) 未定义,则返回 true。
  3. 如果 Type(x) 为 Null,则返回 true。
  4. 如果 Type(x) 是 Number,那么 a. 如果 x 是 NaN,则返回 false。湾。如果 y 是 NaN,则返回 false。C。如果 x 与 y 的数值相同,则返回 true。d。如果 x 为 +0 且 y 为 -0,则返回 true。e. 如果 x 为 -0 且 y 为 +0,则返回 true。F。返回假。
  5. 如果 Type(x) 是 String,则如果 x 和 y 是完全相同的字符序列(相同的长度和对应位置的相同字符),则返回 true;否则,返回假。
  6. 如果 Type(x) 是布尔值,如果 x 和 y 都为真或都为假,则返回真;
于 2012-09-11T17:26:39.987 回答