JavaScript-===vs===运算符性能



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

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

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

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

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

另一方面,标识运算符===不执行类型强制,因此它不会转换值的值比较时

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

我觉得最好是有易于验证的证据的答案。

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

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

如果你减去控制测试,它们在我的浏览器上的速度似乎有大约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);

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

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

typeof的情况下,正如您的问题中所提到的,两个操作数保证是相同的类型(字符串),并且两个运算符将做完全相同的事情,因此,支持一个运算符而不是另一个运算符的唯一原因是风格

JS社区作为一个整体在这方面相当强硬:共识似乎是"除非需要类型强制,否则永远不要使用C0和!=",这对我的口味来说太教条了。

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

这是一种脚本语言。这些运算符的性能不应该太重要,以至于你应该担心它,因为还有很多其他事情需要消耗更多的功率,比如它在虚拟机中运行,类型弱,在浏览器中使用HTML DOM。。。

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

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

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

但无论如何,你可以很容易地测试它(确保你测试了多个案例,既有相同类型的,也有几种不同类型的),但如果你不知道如何测试它,我就不再担心它了。差异,如果有的话,不会杀死你。

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

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

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

来自ECMA标准:

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

  1. 如果Type(x)与Type(y)不同,则返回false
  2. 如果Type(x)为Undefined,则返回true
  3. 如果Type(x)为Null,则返回true
  4. 如果Type(x)为Number,则a.如果x是NaN,则返回false。b.如果y是NaN,则返回false。c.如果x与y是相同的Number值,则返回true。d.如果x是+0,y是-0,则返回true。e.如果x是-0,y是+0,则返回true。f.返回false
  5. 如果Type(x)是String,那么如果x和y是完全相同的字符序列(长度相同相应的位置);否则,返回false
  6. 如果Type(x)为布尔型,则如果x和y都为true或都为false,则返回true

最新更新