Check out a free preview of the full Deep JavaScript Foundations, v3 course:
The "Double & Triple Equals" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle compares the behavior of double equals and triple equals, which are often mistakenly defined. - https://static.frontendmasters.com/resources/2019-03-07-deep-javascript-v2/deep-js-foundations-v2.pdf

Get Unlimited Access Now

Transcript from the "Double & Triple Equals" Lesson

[00:00:00]
>> Kyle Simpson: As I've been making this case for coercion, one of the things that may have been floating in the back of your mind is, yeah, but the coercion problem that I have is not with the plus operator, or an if statement. The big coercion problems that most people seem to have seem to center around equality checking.

[00:00:19] And the same message that I have for all of coercion is going to apply for coercive equality as well. But I wanna dig specifically into some issues about the == versus ===, since this is really the place where most people focus their attention when they talk about coercion.

[00:00:35] In fact most people haven't thought about coercion any other place other than the == verse the ===. So there's some further dissection. So how many of you have heard before that the difference between == and === is that == checks the value so called loose equality and === checks the value in the type so called strict equality?

[00:01:02] This is extremely common. And unfortunately even though it sounds really good it's not exactly the case. That's not exactly the difference. And it's not just an academic nuance here. The difference really changes our perspective on the utility, the purpose of these two mechanisms in our language. So, I really think that if you're trying to understand your code, it's critical that you learn to think like JavaScript, that's sort of been the thesis going along.

[00:01:35] And the same is true for double equals and triple equals, that just saying, well, it's sort of one seems to check the type and the other doesn't. That may get you by in some circumstances, but in other circumstances it leads you to completely different conclusions. So consistent with everything else that we've done, let's look at the spec.

[00:01:54] This is the spec for what is called abstract equality comparison, which is the double equals. And if double equals only checks the value and triple equals checks the value and the type, then why write up here at the very top of the algorithm, the very fast thing, are the types of x and y checked?

[00:02:12] Immediately we can debunk the myth that the difference between these two is whether the types are the same. That isn't the difference. They both checked the types, it's just that one does something different with that information than the other one, okay? So number 1, the source of truth is always the spec, as we keep saying.

[00:02:30] And if you choose to persist in not completely correct mental models that seem to work in some scenarios, eventually the longer the time span goes, eventually you'll run into a case where you're in a different scenario, your mental model is busted, and now you're lost. I think it's better to have the correct mental model.

[00:02:50] Just like the other places of the spec that I have cited for you, this is an algorithm with if statements and then statements and variables and operations. So it's something that you as a developer can understand. The vast majority of JavaScript developers have never once read this section.

[00:03:07] All they've ever heard about the double equals is what is said online about double equals and in books about double equals. Which is almost never citing what the spec talks about. But only citing some anecdotal evidence why they think it's worthy. So reading the spec can be useful.

[00:03:27] For example, if I have a string, Frank, that I've assigned to one variable, and then I create another copy, essentially, that's what's happening on line 2, so now I have two strings. And if on line 7 I try to ask if those two are equal, like I am on line 7 and line 8.

[00:03:44] In both cases, they are equal. Because it turns out that when the types match, then they do the ===. The double equals and the triple equals are exactly identical when the types match. There is absolutely no difference. And the spec says so. When the types match, do the triple equals.

[00:04:04] That's what I just highlighted for you. And we can see that in code. In any place where the value types already match, and by the way, as I said a bunch of times already, you should try to have the value types obvious, and ideally, you should have them matching as much as possible.

[00:04:22] That doesn't mean you can never have coercion, but you shouldn't have lots of places where you're doing comparisons. You certainly shouldn't be doing equality comparisons and have absolutely no idea what the types are. It's interesting to me that many people seem to suggest that it is impossible for them to program and understand what types could be coming in to this comparison.

[00:04:42] And I don't know how you can write any algorithm without having some sense of well these are always numbers and these are always strings. How can you say, well I have no idea? It could be an array it could be null. I have no idea what it could possibly be.

[00:04:56] And even if you don't know, that doesn't mean that it has to stay that way. You can choose to redesign your code so that you've narrowed the surface area of places where those different kinds of types can intermatch, can interweave with each other. You've narrowed those corner cases that exist with coercion.

[00:05:16] So I wouldn't write a function that could take null, undefined string, number, object, array, and 14 other types, and then all compare them with a ==, that's ludicy, right? But I would write a function that could take strings and numbers and compare them with a ==. Because there's a very known and small subset of potential corner cases to work around.

[00:05:39] And those are avoidable if you pay attention. So in the case where the types already match, == and === are the same. So what is === doing? Well, it's also checking the types, and if they're not the same, it's false. It doesn't matter what the values are, if the types are different, it doesn't do anything else.

[00:05:59] It sorta short-circuits and says, if the types are different there's no possible way that they could be equal. If you think about that with respect to what double equals is gonna do, which we're gonna look at in just a moment. Essentially the real difference between strict equality and loose equality is whether or not we're going to to allow any coercion to occur.

[00:06:22] So what us Strict Equality is gonna do if the types are the same? Well it's going to, return false if they're NaNs, because remember it's supposed to lie about NaNs. And it's gonna return true if there's a negative zero because it's supposed to lie about negative zeros. But it only does the lies if the types already match.

[00:06:42] Otherwise, it says false and it didn't check anything at all. So maybe the more appropriate statement would be that they both check the types one of them stops early and one of them doesn't. Or said a different way, the difference is whether we allow coercion. So here, I have two objects, all right?

[00:07:01] They have the same structure and ostensibly the same value. But they are not the same object. They are two different objects. A lot of times people get confused with JavaScript's built in equality checking that it's somehow not structural in nature, that it doesn't do like a deep assertion check that the structure of one object is exactly the same as a structure of another object.

[00:07:23] Maybe there are languages like that, but I don't know of that to be a prevailing thing that's built into an operator in a language. Most operators seem to do what JavaScript does, which is identity comparison. If workshop1 and workshop 2 pointed at literally the same object reference then their identity would be the same and you'd get true.

[00:07:44] But in this particular case, they're not equal, okay? So neither == nor === is gonna return a true because they are different objects. Everybody follow me? They're different objects, they are not the same. And so it doesn't matter which one you use, you're still gonna get the same result.

[00:08:05]
>> Kyle Simpson: So in other words, the == is going to allow coercion when the types were different. And the === is going to disallow coercion when the types are the same.