I'm using JSLint to go through JavaScript, and it's returning many suggestions to replace == (two equals signs) with === (three equals signs) when doing things like comparing idSele_UNVEHtype.value.length == 0 inside of an if statement.

Is there a performance benefit to replacing == with ===?

Any performance improvement would be welcomed as many comparison operators exist.

If no type conversion takes place, would there be a performance gain over ==?

@minitech it should be as it does not do type conversion
– Umur KontacıJul 14 '12 at 19:10

19

@minitech, I doubt anyone is going to make their application noticeably faster by using === over ==. In fact, the benchmark doesn't show a big difference between both on modern browsers. Personally, I usually use == everywhere unless I really need strict equality.
– this.lau_Dec 25 '12 at 9:09

5

Here is the part of Crockford's JS The Good Parts talk where he discusses the === and == operators: youtube.com/… If it doesn't play, it's at 15:20
– davidhigginsApr 22 '13 at 16:17

The == operator will compare for equality after doing any necessary type conversions. The === operator will not do the conversion, so if two values are not the same type === will simply return false. Both are equally quick.

JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. If the two operands are of the same type and have the same value, then === produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. the rules by which they do that are complicated and unmemorable. These are some of the interesting cases:

The lack of transitivity is alarming. My advice is to never use the evil twins. Instead, always use === and !==. All of the comparisons just shown produce false with the === operator.

Update:

A good point was brought up by @Casebash in the comments and in @Phillipe Laybaert'sanswer concerning reference types. For reference types == and === act consistently with one another (except in a special case).

The special case is when you compare a literal with an object that evaluates to the same literal, due to its toString or valueOf method. For example, consider the comparison of a string literal with a string object created by the String constructor.

Here the == operator is checking the values of the two objects and returning true, but the === is seeing that they're not the same type and returning false. Which one is correct? That really depends on what you're trying to compare. My advice is to bypass the question entirely and just don't use the String constructor to create string objects.

=== is not quicker if the types are the same. If types are not the same, === will be quicker because it won't try to do the conversion.
– Bill the LizardDec 31 '08 at 3:02

478

=== will never be slower than ==. They both do type checking, so === doesn't do anything extra compared to ==, but the type check may allow === to exit sooner when types are not the same.
– Bill the LizardFeb 2 '09 at 4:17

224

Replacing all ==/!= with ===/!== increases the size of the js file, it will take then more time to load. :)
– Marco DemaioMar 31 '10 at 9:22

81

"...the rules by which they do that are complicated and unmemorable..." Now such statements make you feel so safe when programming...
– JohanDec 9 '11 at 16:24

In the first statement, are you sure that 'true' is converted to 1 and not 1 converted to true?
– Shadi NamroutiNov 22 '16 at 10:05

Where do the terms "equality" and "identity" come from? The standard does not use those terms. It calls == "abstract equality" and it calls === "strict equality". Granted calling == any kind of "equality" is IMHO awful, since it is not transitive, but why quibble? I take more issue with "identity" though; I think that term is pretty misleading, though it "works." But seriously, who coined the term "identity"? I search the standard and could not find it.
– Ray ToalFeb 7 '18 at 8:03

from my experience using three equals can cause problems and should be avoided unless fully understood. two equals produces much better results because 99% of the time I really don't want types to be equal.
– vsyncFeb 12 '17 at 8:47

7

@vsync: If you really don't want types to be equal, you should use three equals!
– SNagApr 24 '17 at 5:19

In the answers here, I didn't read anything about what equal means. Some will say that === means equal and of the same type, but that's not really true. It actually means that both operands reference the same object, or in case of value types, have the same value.

This behavior is not always obvious. There's more to the story than being equal and being of the same type.

The rule is:

For value types (numbers):a === b returns true if a and b have the same value and are of the same type

For reference types:a === b returns true if a and b reference the exact same object

For strings:a === b returns true if a and b are both strings and contain the exact same characters

Strings: the special case...

Strings are not value types, but in Javascript they behave like value types, so they will be "equal" when the characters in the string are the same and when they are of the same length (as explained in the third rule)

var a = new String("123");
var b = "123";
alert(a === b); // returns false !! (but they are equal and of the same type)

I thought strings behave like value types? Well, it depends who you ask... In this case a and b are not the same type. a is of type Object, while b is of type string. Just remember that creating a string object using the String constructor creates something of type Object that behaves as a string most of the time.

Thank you for explaining why new String("123") !== "123". They are different types. Simple, yet confusing.
– styfleAug 26 '12 at 5:51

20

String objects behave as strings as does any other object. new String should never be used, as that doesn't create real strings. A real string and can be made with string literals or calling String as a function withoutnew, for example: String(0); //"0", Real string, not an object
– EsailijaDec 4 '12 at 23:51

6

But in the cases you detailed, the operator "==" behaves exactly the same.
– Yaron LeviFeb 6 '15 at 10:48

ECMA-262 is the specification for a scripting language of which JavaScript is a dialect. Of course in practice it matters more how the most important browsers behave than an esoteric definition of how something is supposed to be handled. But it is helpful to understand why new String("a") !== "a".

Please let me explain how to read the specification to clarify this question. I see that in this very old topic nobody had an answer for the very strange effect. So, if you can read a specification, this will help you in your profession tremendously. It is an acquired skill. So, let's continue.

Searching the PDF file for === brings me to page 56 of the specification: 11.9.4. The Strict Equals Operator ( === ), and after wading through the specificationalese I find:

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 not Number, go to step 11.
5. If x is NaN, return false.
6. If y is NaN, return false.
7. If x is the same number value as y, return true.
8. If x is +0 and y is −0, return true.
9. If x is −0 and y is +0, return true.
10. Return false.
11. 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.
12. If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
13. Return true if x and y refer to the same object or if they refer to objects joined to each other (see 13.1.2). Otherwise, return false.

Interesting is step 11. Yes, strings are treated as value types. But this does not explain why new String("a") !== "a". Do we have a browser not conforming to ECMA-262?

Not so fast!

Let's check the types of the operands. Try it out for yourself by wrapping them in typeof(). I find that new String("a") is an object, and step 1 is used: return false if the types are different.

If you wonder why new String("a") does not return a string, how about some exercise reading a specification? Have fun!

Aidiakapi wrote this in a comment below:

From the specification

11.2.2 The new Operator:

If Type(constructor) is not Object, throw a TypeError exception.

With other words, if String wouldn't be of type Object it couldn't be used with the new operator.

new always returns an Object, even for String constructors, too. And alas! The value semantics for strings (see step 11) is lost.

Result of Type(x) is implied to be the same as typeof ?
– DfrNov 15 '12 at 18:35

@nalply I don't exactly understand the anxiety about the behavior with new String('x'), because I've never seen any code in the wild that uses primitive wrapper objects, and I don't think there's much good reason to, especially not these days. Have you ever encountered code that does?
– AndySep 10 '18 at 18:28

@Andy the problem is malicious or just sloppy third-party code, then you can't assume that nobody uses new String().
– nalplySep 11 '18 at 9:46

If it's sloppy, === is how you will find out. If it's malicious, I think new String() is probably the least of your worries. I understand the concern in theory, but again, do you have any real-world examples? To me it's like the old anxiety that someone could set undefined to another value.
– AndySep 12 '18 at 15:34

Yes: Two different objects with the same type and value compare false, i.e., this answer is just wrong. Why does it have 50 upvotes?
– alexisOct 18 '13 at 10:45

1

I realize this is old, but to clarify why this answer is still "correct" is because in the example var a = {}, b = {}; While both a and b is indeed both an object, but they are not the same value, technically speaking. They are different instances. Note that comparing instances behaves differently than comparing primitives. Which probably adds to this confusion. You will see similar comparison behavior if you use instance version of primitive data types. E.g new String('asdf') or new Number(5). Ex: new Number(5) == new Number(5) is false, even though they hold the same value.
– Norman BreauMay 18 '17 at 18:02

1

We all forget that a reference to an object is actually a Value Type, as it a pointer to a memory slot. The Object comparison is not comparing the "value of the object" but whether both pointers are the same which would mean they reference the same memory slot. That is a very subtle difference in comparing Types, as the "===" operator really needs to say "if type, value, and reference to the object in memory are the same".
– StokelySep 3 '18 at 20:05

So I'd say that the miniscule difference (this is over 100000 iterations, remember) is negligible. Performance isn't a reason to do ===. Type safety (well, as safe as you're going to get in JavaScript), and code quality is.

Your looseEqual is wrong. Function == Function.toString() is true, but looseEqual(Function, Function.toString()) is false. Not sure why you filter out functions at the beginning.
– OriolSep 7 '16 at 22:16

@Oriol you were right, I updated the code to account for that, FYI based on my tests it wasn't enough to remove the filter for "functions", instead "functions" had to be handled differently altogether.
– Luis PerezSep 8 '16 at 22:43

I tried treating functions and objects the same but found he results were incorrect. For example if functions were treated like objects then comparing a function with an object that implements valueOf() or toString() function that matches the function would pass but in reality it doesn't. Example: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}} - check out this JS Fiddle which runs all the tests: jsfiddle.net/luisperezphd/7k6gcn6g (there 1,225 test permutations)
– Luis PerezSep 10 '16 at 16:22

1

You're right, great observations, this emphasizes the main point that == does a lot of things making it very difficult to anticipate the results while === is much more straightforward and predictable which is one of the main reasons === is the recommended choice. (I'll add a note to the answer mentioning your point)
– Luis PerezSep 11 '16 at 13:20

I don't understand why the string arrow is pointing to the big gray box, is it supposed to mean the interrupter is casting the string to a number?
– vsyncFeb 11 '17 at 13:26

@vsync It points to the string option within the grey box i.e string -> # || NaN. Javascript is not a type-script language i.e basically it can have any type of variable. So, it is pointed to that grey box.
– Samar PandaFeb 12 '17 at 6:56

I simply asked if it is for casting purposes since the string is supposed to be compared to a type number, so the interrupter looks at what the string should be compared to and cast the string accordingly?
– vsyncFeb 12 '17 at 8:44

The big gray box is what ToNumber would return when given different types, so if it is given a string it will only choose the last option (and convert it to a number). == uses ToNumber only in the cases string == number or boolean == anything above (and only on the string/boolean). This means == will never convert undefined or null even though they are in the gray box. (For any combination of either undefined or null or both, == will always return true. Also, whether a value is on the left or right side doesn't matter, == (and ===) will return the same result.)
– user2033427Mar 7 '18 at 5:54

It means equality without type coercion
type coercion means JavaScript do not automatically convert any other data types to string data types

0==false // true,although they are different types
0===false // false,as they are different types
2=='2' //true,different types,one is string and another is integer but
javaScript convert 2 to string by using == operator
2==='2' //false because by using === operator ,javaScript do not convert
integer to string
2===2 //true because both have same value and same types

In a typical script there will be no performance difference. More important may be the fact that thousand "===" is 1 KB heavier than thousand "==" :) JavaScript profilers can tell you if there is a performance difference in your case.

But personally I would do what JSLint suggests. This recommendation is there not because of performance issues, but because type coercion means ('\t\r\n' == 0) is true.

There is unlikely to be any performance difference between the two operations in your usage. There is no type-conversion to be done because both parameters are already the same type. Both operations will have a type comparison followed by a value comparison.

It's a good thing especially if you're checking between 0 and false and null.

For example, if you have:

$a = 0;

Then:

$a==0;
$a==NULL;
$a==false;

All returns true and you may not want this. Let's suppose you have a function that can return the 0th index of an array or false on failure. If you check with "==" false, you can get a confusing result.

The top 2 answers both mentioned == means equality and === means identity. Unfortunately, this statement is incorrect.

If both operands of == are objects, then they are compared to see if they are the same object. If both operands point to the same object, then the equal operator returns true. Otherwise,
the two are not equal.

In the code above, both == and === get false because a and b are not the same objects.

That's to say: if both operands of == are objects, == behaves same as ===, which also means identity. The essential difference of this two operators is about type conversion. == has conversion before it checks equality, but === does not.

The problem is that you might easily get into trouble since JavaScript have a lot of implicit conversions meaning...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Which pretty soon becomes a problem. The best sample of why implicit conversion is "evil" can be taken from this code in MFC / C++ which actually will compile due to an implicit conversion from CString to HANDLE which is a pointer typedef type...

CString x;
delete x;

Which obviously during runtime does very undefined things...

Google for implicit conversions in C++ and STL to get some of the arguments against it...