Deep JavaScript Foundations, v3

Double Equals Walkthrough

Kyle Simpson

Kyle Simpson

You Don't Know JS
Deep JavaScript Foundations, v3

Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "Double Equals Walkthrough" 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 walks through a few lines of code that utilize the double equals for coercive equality.


Transcript from the "Double Equals Walkthrough" Lesson

>> Kyle Simpson: If you use a double equals between, in this case, a number and an array that holds the number. This is a really terrible idea. You should never write code that compares a primitive to an array like that. But if you did, if for some reason you wrote a function that couldn't control whether somebody passed a number or an array with a number in it, would it work coercively?

In this particular case, yes, but should it? Ooh, and why is more important, even, than does it work? Why would this one work? Why would a number somehow be coercively equal to an array holding that number? And certainly only in the case where that array only has the single number, not if it had multiple numbers, right?

So let's again, let's invoke that algorithm to see what is actually happening under the covers. To get a sense of what double equals is doing. First, it tries to compare workshop1Count and workshop2Count. That's the ==. It turns workshop1Count into its primitive form, which is its number. But workshop2Count is an array, so what it first does is say toPrimitive.

What happens to the toPrimitive of an array? It stringifies itself, so then we end up with line 5, 42 == "42", right? But that’s only because of that weird array stringification that doesn’t include the brackets. So it’s almost accidentally working here. And only accidentally working because there is only one value in the array.

You with me? Now we have two different types, we have a number and a string. There's two options here. We could either make the number into a string and compare the strings, or make the string into a number and compare the numbers. Which one happens in the algorithm?

It prefers-
>> Speaker 2: Numerification.
>> Kyle Simpson: Numeric comparison, so the string becomes the number, and notice here, line 6, it does a triple equals because the types are now the same.
>> Kyle Simpson: You follow that line of reasoning? Now this is obviously a contrived example, but the point here is that even if it works, that doesn't mean you should use it.

This is one of those clear examples I think where coercion is a very bad thing for us. You should reduce the surface area and not make comparisons between numbers and arrays of numbers. That doesn't even make any sense in programming. And yet that's where most of our corner cases that we get bitten by are, because we do all of that polymorphic typing stuff.

We should never do that. And you shouldn't fix this problem by using triple equals. Okay, most important take-away here, the fix here is not to use triple equals. Triple equals prevents you from seeing the real problem, which is that you're making a terrible comparison in the first place.

What you should do is fix it so that the comparisons that you're making make sense.
>> Kyle Simpson: Yes.
>> Speaker 3: I mean, I understand you did this to demonstrate a point, but if I would look at code like this, wouldn't you say that that person has bigger problems than that?

>> Kyle Simpson: That's exactly my point.
>> Speaker 3: Yeah.
>> Kyle Simpson: There are bigger problems here. This is not a, you should go use double equals this way. This is, this is what people complain about with double equals, and they're saying that double equals is the problem. And the real problem is that you're making a nonsensical comparison.

Double equals isn't the one that's at fault. And triple equals only covers it up, it doesn't fix the real problem. If you make sensible comparisons, like a string representation of a number to the actual number, that's a sensible comparison and coercion makes complete sense there. But if you compare something to something entirely different and it accidentally works, that's not sensible.

That's not reasonable. I agree with you that the outcome that we see is, why would you do that? But what I don't tend to do is say JavaScript was poorly designed here. There are historical reasons for why it allowed even the two primitives in a comparison. If I were designing the coercion, I would of done all the other coercions but not included the two primitives, because in my opinion the only kind of non-primitive comparison that should ever be possible is the identity comparison.

Coercion with primitives is crazy. But one of the historical reasons for the coercion with primitives is that in the olden days you did newString, and now you have an object. But you don't think of it as being an object, you think of it as being the primitive. So they allowed that non-primitive to coercively down coerce itself to its primitive equivalent.

That's why the algorithm has something like that. I wouldn't write that code, but that's why it's there. So it's hard to say that's a poor design, in my opinion.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now