Deep JavaScript Foundations, v3

Coercive Equality

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 "Coercive Equality" 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 discusses the choice to use double equals or triple equals and how linters can both help and hurt code.


Transcript from the "Coercive Equality" Lesson

>> Kyle Simpson: And I would claim that just like every other operation, it is helpful if you understand what the types are. Like every other operation, you have to ask yourself, if I know the types, is coercion here helpful or not? Maybe it is helpful, maybe it isn't. It's a critical analysis.

It shifts the discussion away from double equals is bad and unpredictable to do I wanna allow a coercive comparison or do I not wanna allow that? In this particular case, is it more helpful to me to do so or is it less helpful? Is it more safe or is it less safe?

In other words, you need to be critical, analytical thinkers, and look at your code. And decide what you can know about your code and what you can't. And essentially the decision about double equals and triple equals is a trailing indicator of whether you actually understand your program. Let me say that again.

Your choice to use triple equals, it's not just because some guy wrote in a book that you should always use triple equals. Your actual choice to use triple equals is a trailing indicator which points back to the fact that you don't know something about the types in that comparison and so you have to protect yourself.

And my opinion is, if at all possible, maybe it would be better to fix the root problem, which is that I don't know what the types are in this comparison. It's too unpredictable, it's too polymorphic.
>> Kyle Simpson: That's gonna lead to better code with fewer bugs, regardless of whether you use a double equals or a triple equals.

Deciding what your types are, making it obvious what those are.
>> Kyle Simpson: So do we know those types? Let's take a look at what the double equals is going to do if the types are different. First off, if the types are null or undefined on either side, that's what these two clauses are paired to say, if x is null and y is undefined or a vice versa, then return true.

In other words, the no value and the undefined value are coercively equal to each other and to no other values in the language, which is what clause 10 says. It says return false. Null and undefined will not match any other clauses in this algorithm, other than clause 2 and 3.

And so it's only coercive to each other. I find that to be a tremendously useful fact about JavaScript because, quite honestly, I don't like having two empty values. I find that to be confusing. So I would much rather deal with one empty value. And since null is shorter to type than undefined, I'd rather deal with null everywhere.

And pretend as much as possible that undefined doesn't exist. Or at least pretend that they're interchangeable. JavaScript does make some distinctions between them, such as the default value algorithm. But, for the most part, you have the option of treating null and undefined as indistinguishable through coercive equality. So you could do a check like this, you could have a workshop one and a workshop two, and there's a topic property on there.

You could be asking of that topic property if it's been set and it's null, or if it's never been set at all, or if it's been set and it's too undefined. You could try to distinguish between those two, but I would argue in almost all cases, that's not a useful distinction.

Whether the property was ever created and has been reset back to null, or whether it's been reset back to undefined, or whether it was never created at all. Those are basically all the same condition, or at least I would argue, that's a better way to code, to treat those as indistinguishable.

So one option is for you to write what you do on lines five and six, which is to use this triple equals that does not allow coercion and explicitly checks all of those cases. Explicitly checks that workshop1.topic is null or workshop1.topic is undefined and the same thing is true of workshop2 topic.

>> Kyle Simpson: Are you gaining anything readability-wise by being explicit here? Ask yourself the question if the reader has benefited from having to juggle in their head the distinction between two empty values?
>> Kyle Simpson: My assertion is that no, they are not benefited. And using the double equals like we do down here on lines 12 and 13, it's far more clear.

It says, whether are null or undefined, tell me if they're empty or not. Tell me if they're one of those two empty values. And by the way, I just picked the shorter of the two cuz it's less to type.
>> Kyle Simpson: Okay? This is an example of using coercive equality, and even some of the staunchest harshest critics of coercion, you will find them using double equals null checks in their code.

Because it's less controversial than some of the other double equals usages. Most people seem to be okay with that. Even though JFLint says no no, most other people have those linting rules turned on. I use ESLint, it's an amazingly configurable linter. I have a very different rule set than you do, I'm sure, cuz I have very different opinions, but I use an ESLint tool and I turn on what rules help me write better code and that's what linters are for.

Linters are an opinion that helps you decide whether or not your code is formatted in such a way where, or structured in such a way, to avoid bugs or whether it's likely that a problem will occur. It's not checking if your programming is correct. It's giving you an opinion on whether you've done the right thing.

The thing about opinions is that everybody's got different opinions. So the best tools are the ones that are most configurable, not just to individual opinions, but most effectively for teams. Let a team decide what is effective for them. To any extent that you use a tool that shares an opinion about your code with you, by way of erroring out your build process, to the extent that that tool is unable for you to configure it so that you can get your job done more effectively and it forces you to change the way you code to adapt to it, then that tool is not helping you, it is hampering your development opportunities.

If it's not smart enough to understand what it's doing. For example, I use ESLint and ESLint's got a bunch of really great rules in, but it's got some rules which are pretty naive. One of those rules has to deal with variable declarations, whether you're allowed to use a variable declaration earlier in the scope.

Now I can clearly say, and we're gonna come back to this in our unit on scope, but I can clearly say to you that I wouldn't recommend saying A equals two and then Var A, that's a terrible usage of that. But that same rule that prevents that also prevents me from saying A equals two inside of a function if the var A isn't above the function in the code.

That's not at all the same thing, but that tool is not at all smart enough to distinguish those two differences in scoping behavior. And that rule gets in my way instead of helping me. So I don't use that rule. Good news about ESLint is you can write your own rules.

I actually just wrote my first ESLint rule plug in. We'll talk about that one a bit later on the course.

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