JavaScript - === vs == operators performance

萝らか妹 提交于 2019-12-17 10:44:29

问题


A few weeks ago, I have read this thread Is < faster than <=? about comparison operators in C. It was said that there is no difference in the performance between < and <= as they are interpreted as same/similar machine commands.

At the same time, in our company's "best practices", it was said that we should always use "===" to compare things instead of "==". So, I started to wonder if this is always appropriate as I am used to using the "==" and "typeof ... == " and do not want to change my way of writing :-]

Note that this is in the context of JavaScript.

So, I have a little research and here Which equals operator (== vs ===) should be used in JavaScript comparisons? it is said that:

This is because the equality operator == does type coercion...meaning that the interpreter implicitly tries to convert the values and then does the comparing.

On the other hand, the identity operator === does not do type coercion, and so thus it does not convert the values of the values when comparing

And I started to wonder if this means that when I use the "===" operator, I will get good performance as no resources will be spent on converting the operands. And after all code is turned into machine commands, does this mean that just as there is no difference in C when you use < and <=, this is the same in JavaScript and other languages?


回答1:


for js, the === operator will return true if used on string types and the strings are exactly the same characters. For objects it compares the object references, not the contents.

From the ECMA standard:

11.9.6 The Strict Equality Comparison Algorithm The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Undefined, return true.
  3. If Type(x) is Null, return true.
  4. If Type(x) is Number, then a. If x is NaN, return false. b. If y is NaN, return false. c. If x is the same Number value as y, return true. d. If x is +0 and y is -0, return true. e. If x is -0 and y is +0, return true. f. Return false.
  5. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
  6. If Type(x) is Boolean, return true if x and y are both true or both false;



回答2:


Firstly, performance simply is not a concern. For any real script, any performance gain of using one operator over the other will be infinitessimally small compared to other bottlenecks in the code (typically DOM manipulation would be the number one target).

Secondly, in many cases, == and === will perform exactly the same steps. When the types of the two operands are the same (two strings or two numbers, for example), the ECMAScript specification has precisely the same steps for the two operators. Therefore if you observe a performance difference between the two operators for operands of the same type in one browser or other environment, it is neither guaranteed nor even probable that you will see a similar difference in another browser.

In the case of typeof, as mentioned in your question, the two operands are guaranteed to be of the same type (string) and both operators will do precisely the same thing, so the only reasons to favour one operator over the other are stylistic.

The JS community as a whole has gone rather hardline on this: the consensus seems to be "never use == and != unless you need type coercion", which is too dogmatic for my tastes.




回答3:


I feel an answer with easily verifiable evidence would be best.

These operations are so small that it is difficult to performance test them.

  • == 1648 true
  • === 1629 true
  • control test 1575 true

If you subtract off the control test, it looks like there is a ~30% difference in their speeds on my browser. If you do this multiple times, you can get different answers, but === usually comes up the fastest, which I think is just a testament to just how negligible the difference is.

I think this pretty much proves what others were saying, that the performance difference is a waste of time to think about, but it also shows that === is actually faster. Hopefully this answer can save other people time, those who simply must see proof.

2019 Updates

2019-04-09 Firefox with improved test:

  • == 1383 true
  • === 1167 true
  • control test 429 true

2019-04-09 Chrome with improved test:

  • == 249 true
  • === 248 true
  • control test 248 true

2019-04-09 Edge with improved test:

  • == 22510 true
  • === 20315 true
  • control test 4968 true

Browsers have gotten smarter over the years and it appears my original test has run up against cool optimizations in Chrome and Firefox, rendering it no longer useful. I have made the test more difficult to optimize and increased the number of runs to get meaningful results again. It looks like === is still faster across the board. It is probably still a waste of time to worry about.

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



回答4:


It doesn't matter what performance you get, === is clearly the better choice in this case. Anything else such as better performance is just the icing on the cake. Besides, the difference either way is minimal.




回答5:


The performance difference is negligible, which means you should not waste your precious brain cycles thinking about it. If you really want to know though, you should test.

Use === unless you have a great reason not to (you probably don't).




回答6:


It's a scripting language. The performance of these operators shouldn't matter so much that you should worry about it, because there's a bunch of other things that consume much more power, like the fact that it runs in a virtual machine, is weak typed, works with a HTML DOM inside a browser...

Besides, both operators do quite different things, so one might not be interchangable with the other in any case.

That said, I think (but have not tested) that === is faster. The reason being, that it only needs to compare the type, and if that matches, compare the raw data. The == operator will try to convert one type to another if they don't match. This will be a more expensive operation in most cases.

And that is fortunate, because in most cases === is the better option. :)

But anyway, you can easily test it (make sure you test multiple cases, both with same type and a couple of different types), but if you don't know how to test it, I'd stop worrying about it altogether. The difference, if any, is not going to kill you.



来源:https://stackoverflow.com/questions/12374815/javascript-vs-operators-performance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!