Transcript from the "Negative Zero" Lesson
>> Kyle Simpson: Moving on to our next special value. We'll talk about negative zero. You're gonna have to suspend some of your mathematic belief for just a moment, and pretend that there is such a thing as a negative zero. And if in that hypothetical world there is, can we all at least agree that if there is a negative zero, basically the only way to get a negative zero would be to do a multiplication or division with a negative value and zero.
[00:00:24] Because it wouldn't make any sense to add up or subtract to a negative zero. It's not like negative three plus three would be negative zero or something like that. So multiplication or division would be the only way that we could result in such a value, okay? So if we were to take zero and divide it by negative three, it should result in this negative 0 value should one exist.
[00:00:45] And it turns out if we test for it, we get true. But unfortunately, if we test for the regular zero, we also get true. So line 3 lets us know there's something weird going on. How can it both be negative 0 and 0? And many people stop at line 3 and just assume well, okay, I guess there isn't a negative zero, it's just ignoring that minus sign.
[00:01:54] What that means is when we deal with negative zero, we are operating on that zero. It's not like negative 0 is just ignored, it's that we are taking the regular 0 value on line 2 and negating it. So we are producing the negative zero value. But how is it that foo can be triple equal to negative zero and to regular zero?
[00:02:13] Well, the problem is not that there isn't a negative zero, but that the triple equals operator lies to us. And it doest that on purpose. If you read the spec, it literally says if there's a negative zero, return true. So y isn't lying to us. Well, this is kinda what I was talking about earlier.
[00:02:51] So I can imagine one of this cases that they really wanted to avoid was somebody showing up within their quantity field on an e-commerce forms, negative zero for the quantity zero. Cuz that doesn't make any sense, right? And it doesn't make any sense to a user. So how could we end up with a negative zero here?
[00:03:08] So, what they basically did was when they said all the different operations that could operate on a negative zero, just make it pretend as if you were operating on a regular zero. In other words, try to hide the fact that there is a negative zero. Which is why the === operator here works.
[00:03:24] Even when negative zero is compared to regular zero, it actually says true. That's a strange choice, and it's even true if you try to coerce it to a string. If you try to take the negative zero and call two string on it, or negative zero and pass it in the string function then you're gonna get regular zero instead of negative zero, which is bizarre, right?
[00:03:47] But again, it was because they were trying to hide the fact that this exists. So in all of our cases of how we wanna try to test for the negative zero, it fails for us. Even if you try this in your browser, and you type in foo. Up until about a year, a year and a half ago, it would print regular zero in the browser console instead of negative zero.
[00:04:10] And then it finally started passing it, because I complained enough to the browser vendors, the development tool teams. Because I'm a teacher and I spend a lot of time teaching people in web developer consoles, it's frustrating to me when the web developer console doesn't work the way it ought to.
[00:05:30] And that is to put it in its own file and load that file in a webpage, that's it. Every other environment, you're gonna need to have that caveat in mind, that they might be doing funky stuff like changing the way something prints, because they think it's more friendly to a developer or something.
[00:05:47] This was basically lying to developers and that was my case. I said, quit lying to developers, that's not helping anything. Tell them the truth, okay? I fought this battle about a dozen times on different topics and I've had about a 50, 50 success rate of convincing them. Stop doing stupid stuff that makes it hard for developers to understand what they're doing, okay?
[00:06:29] So just keep that in mind.
>> Kyle Simpson: So, if we can't test for foo being negative zero in any way that we have meaningful to us. The stringification, the equals, all these systems are gonna lie to us. How do you think we can test for negative zero?
>> Speaker 2: Check for reciprocal of its negative infinity?
>> Kyle Simpson: Turns out if we divide it into 1, we're gonna get negative infinity. That's the only way we can get negative infinity with the division, is if we add a negative 0. We need to check to make sure it's one of the two zeroes. That's what the ===0 check is on line 2, cuz negative infinity would also also equal negative infinity.
[00:07:10] [COUGH] But we need to make sure we, if it is one of the two zeroes, then we can divide it into one and get a negative infinity. So this is a reliable check for negative zero, okay? Now, you might be wondering, why on earth, this is a bunch of academic stuff, why on earth would I care about a negative zero?
[00:07:32] There are some mechanisms that have been in place, and I have legitimately actually used this once in real code. There are some mechanisms, which encode into a number multiple pieces of information. In particular, they will use the magnitude of the number, the size of the number, to represent something like how fast something is moving in animation, for example.
[00:07:54] And they'll use the sign of the number to encode the direction of movement. I use this in a navigation sort of app, where the number represented how fast the car was moving on this map as it was being plotted. And then the direction was encoded by the number, wasn't moving left or right, okay?
[00:08:12] So think about the moment when it goes to zero. If you were to lose the sign, it would lose the orientation of that little car. I wouldn't be able to know if it was facing left or right, where was it moving when it stopped? What direction was it moving?
[00:08:27] I'd lose that information. So being able to encode direction as part of this value in the sign is kind of an important thing, and we don't want to lose that information when we go to zero. That's one example of wanting a negative zero for capability's sake. And I'm not saying that's gonna be a common thing across all your applications, but it should exist and we should be aware of that.
>> Kyle Simpson: All right, now both the NaN check and the 0 check that we're talking about, they feel a little bit contrived. And so they added a new mechanism in ES6 called Object.is. I do not like where they put it. I think it's a terrible idea to put it on the object namespace, because it implies that we're dealing something with objects.
[00:09:37] If you think about double equals is doing one thing, and then triple equals seems to be a more strict check. But it still lies to us on the topic of negative zero and on the topic of NaN. The object that is, is the quadruple equals which doesn't do any lying.
[00:09:51] My little anecdote for this is I don't know if anybody remembers. But the TV commercials for, there's a brand of men's shaving razor called Mach or something like that. I don't know, years and years ago, they had the Mach one and had the single blade. And then it was a big deal when they came out with the Mach two and it had two blades.
[00:10:09] Then a year later, there came out with the Mach three and it had three blades. And you're like, all right, it's getting a little bit ridiculous, right? And then they had like four, five, six, seven. I think they're on like Mach 28 now or something, they just keep adding more blades.
[00:10:42] But in the specific case of NaN and negative zero checking, you absolutely should use the Object.is, okay? So for NaN or negative zero checking or both, use Object.is because it will well, and true, and faithfully tell you the answer to your question without any lying whatsoever.
>> Kyle Simpson: All right, so those are our special types, our special values within the perimeter types.
[00:11:08] Quiz, baz = 2, what is the type of baz?
>> Kyle Simpson: Quote number, good, right? Now, I say var baz again and then I say type of baz on line 4, what is the type of baz?
>> Students: [INAUDIBLE]
>> Kyle Simpson: I hear different answers. Only some of you are correct.
[00:12:01] So var baz on line 3 is a no op, it does not actually do anything at all to the baz. The compiler would see that and ignore it as a no op operation, okay? In which case, line 4 is exactly the same as line 2, baz is still in its existent state.
[00:12:17] That's why we're getting quote number. And, what about line 5? I say baz = null. And then line 6, what's gonna be the type of baz?
>> Students: Quote object.
>> Kyle Simpson: Quote object. Instead of quote null like it ought to be, it's gonna say quote object. All right, now line 8, [COUGH] I take a string, the string baz, and I multiply it by 3.
>> Students: Add the number.
>> Kyle Simpson: Okay, it's gonna try to coerce, quote baz into a number, that's gonna fail resulting in Nan.
[00:13:02] We're gonna have the invalid number Nan, and Nan times 3 is still gonna be Nan. Now, but what about the type of baz on line 10?
>> Students: Quote number.
>> Kyle Simpson: Quote number, okay? Baz = 1 divided by 0 on line 12, what is the value of baz in line 13?
>> Speaker 4: Infinity.
>> Kyle Simpson: Infinity. And what is the type of baz?
>> Speaker 4: Quote number.
>> Kyle Simpson: Quote number. Infinity is a number. I've actually had people suggest it should be something other than a number. It's definitely a number, okay?