JavaScript: The Hard Parts, v3

ToPrimitive Coercion

Will Sentance
Codesmith
JavaScript: The Hard Parts, v3

Lesson Description

The "ToPrimitive Coercion" Lesson is part of the full, JavaScript: The Hard Parts, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Will explains how Date objects can be automatically coerced into primitive values, such as numbers, through a hidden method called @@toPrimitive. This enables operations like subtracting two Date objects to get the difference in milliseconds. The coercion happens because the language calls the @@toPrimitive method, which returns a numeric value representing the date, allowing math to be performed on these objects.

Preview

Transcript from the "ToPrimitive Coercion" Lesson

[00:00:00]
>> Will Sentance: Let's have only 1 second pass between these two. I don't know why I changed to that, and then let's see if there's surely no way to compare the objects directly. Surely, it's impossible. Surely I can't do time 2, which is this object, minus time 1, which is this object. Surely there's no way we can do that. That would be impossible. Could we subtract the objects from each other to see if the difference is less than 2000 milliseconds?

[00:00:31]
Surely not. Who thinks the answer is yes? No, okay. Who thinks the answer is no? Okay, that would make no sense, and yet we can, introducing our ToPrimitive coercion. It is going to automatically coerce both of these objects, time 2 and time 1, to a primitive, in this case, a number. And in this case, the number, the date value, hidden property. Flipping heck, we're going to get the ability to automatically convert, coerce our objects into a number, not compare their positions in memory like we were before, not try and do math on their positions in memory, in the underlying heap or, you know, the flexible store, but instead have this object and this object auto coerce, auto run ToPrimitive into a number.

[00:01:33]
So here we go, let's do it, and then let's ask how the heck was this possible, and even could we perhaps start doing that on our own objects? Because that would be pretty cool to control that pipeline ourselves. So, let's adjust. I don't quite know why I started with 3 seconds passing, but I don't see the harm. Let's adjust to 1 second passing, and so 1 second past, so our user is going to be submitting their order at midnight on January 15th, 2027.

[00:02:10]
Fortunately, that is 1.8 trillion milliseconds after, thank goodness. And then 1 second later, they're going in quick succession, submit again. What, our expert in long numbers, Chris, what is going to be the number of milliseconds at 1 second after midnight? 1.8 trillion and 1000. Oh, that's beautiful. Yes, thank you very much. You know, it's these, I know these things seem, we're all grateful when someone actually tracks along.

[00:02:42]
So perfect, let's get rid of our property assignment. As I say, I did that because I wanted to show you that these are just regular objects. And I also, I mean it's done, there they are, and I also did that because I really want you to keep track of what happens when we do square bracket property assignment, because it really is a gotcha. And now let's hit this conditional.

[00:03:18]
If time 2 minus 1 is less than 2000, then do something. In this case, console log accident. Let's evaluate this statement. Time 2 is what position in memory, Chris, with our kind of proxy, roughly? 10,002. Yeah, we're sort of just saying roughly, right? We're not being, but we know it's an address to a position in memory, and the other one is 10,001. We're not getting great pen action here.

[00:03:53]
Hopefully this helps. There we go. Is that what we're going to be doing here? That ain't no good. In some languages, by the way, we could do pointer math and actually evaluate that. I mean, it wouldn't make any sense here anyway. No. People, you know what's going to happen here? I think it's quite cool actually. JavaScript is going to kick off a ToPrimitive. Primitive is here, a number, a string, and in this case it's going to be ToNumber.

[00:04:31]
We'll see why in a moment. A ToPrimitive, well actually we know why, because we've got some math happening, which is going to kick off ToNumber or ToPrimitive, with a number adjuster, on our time 2 and our time 1 object. Our time 2 is going to coerce to our hidden date value property of 1.8 trillion plus 1000. Our time 1 to 1.8 trillion. Chris, what is 1.8 trillion plus 1000 minus 1.8 trillion?

[00:05:31]
1000. 1000 milliseconds, is that less, Chris, than 2000 milliseconds? Yes it is. It is. Yay. Therefore, accident too soon. People, we've managed to rely on JavaScript's automatic coercion pipeline from an object, two objects here into a primitive, such that we can do math on objects. Not only that, it's been vital to get this hidden property out of the time 2 and time 1.

[00:06:04]
Now in practice, we have available methods that we can call on our objects that come out of the date built-in function that let us get access to that number. But what a remarkable thing that we also have the ability to treat our object as a primitive, to do math on it. And for the treatment of it as a primitive, doing math on it, it's going to run the ToPrimitive and ToNumber.

[00:06:38]
What a remarkable feature of the programming language. So how is this possible? Via the @@toPrimitive property. The @@toPrimitive property. I really like saying @@ as well. The @@toPrimitive property. The math time 2 minus 1 kicks off object. That's an object, that's an object, doesn't look at their memory position, just says, find me a way to convert these to a number.

[00:07:10]
Well, how the heck do they know the way? Via this @@toPrimitive hidden property. It automatically goes looking on both of these objects, do you have an @@toPrimitive hidden property that is code, functionality, and @@toPrimitive property that is functionality. That has instructions on how to convert, how to coerce this object into a primitive, specifically, and we'll see how to do it, specifically into a number.

[00:07:57]
And you bet it does. The date function ensured that the returned out object had automatically got on it an @@toPrimitive hidden property. One that we can't see or edit, but well actually we can, but we can play with that, but one that is attached to time 1 and time 2, and it is going to grab. It is going to grab our hidden date value property, so that in fact, when we run time 2 minus time 1.

[00:08:33]
We kick off a ToPrimitive coercion flow that is going to run this function, and when it does so, it's going to return out. So there's the @@toPrimitive. It's going to return out at 1.8 trillion plus 1000, and on this side @@toPrimitive is going to return out 1.8 trillion. 1.8 trillion plus 1000, 1.8 trillion. And then we can do the math on it. JavaScript has stored instructions there on how to coerce both time 1 object, time 2 object to their also hidden date value numbers.

[00:09:13]
People, let's get thumbs on this. At this point, you lost me, I'm clear, clarifications. Austin has a clarification, other folks, thumbs out. Joe has a clarification, Michael has a clarification. Brady, where's your thumb at? Brady has a clarification. People, I think it would be amazing if we could use this @@toPrimitive property, not just the one automatically added to our date returned object, but maybe on our own objects too.

[00:09:49]
But if we could, I have a strong feeling it might not be a conventional property, given it's hidden here. And I don't know how I add hidden properties, because they ain't strings, I'll tell you that. But let's go around, let's start with Brady. Are you ready to frame it, or yeah, go ahead. Yeah, so the ToPrimitive, obviously could coerce it into a string or a number.

[00:10:15]
How is it the operator that determines that? Correct. Here it was very much the operator being math that says make both sides numbers. So ToPrimitive with the almost argument of number. We'll see before we finish today, that it literally is an argument, the string, well, the string number. In fact, we'll see before the end of the day that we will run a ToPrimitive function where we will write conditional logic saying if argument is string number, then, so yeah, we're going to come to it.

[00:10:48]
Great question, Brady. Joe? I guess my question also had to do with like how does that ToPrimitive get assigned because I mean an object could have all kinds of data, you could have strings, you could have numbers in there and so is it in this one is auto, this one's auto added. This one is, sorry, go ahead, sorry, forgive me. No, that's, I mean that's the essence of the question is, is this intrinsically assigned to all objects or are there specific objects known that are predetermined?

[00:11:20]
Great question. Great question, and I think it points to the question of when was this @@toPrimitive added to JavaScript. It was added in 2015. 20 years after JavaScript was created. So do all objects have it? Can I add it without breaking prior code when it isn't on all, well it can't have been on all objects, right, because there's a lot I don't have it. So what's going on here?

[00:11:47]
This one is automatically added to output of the function called date, an object that has a hidden property date value and has its own ToPrimitive, @@toPrimitive, sorry, hidden property here. We may want to add it to other objects. I just don't know how I'm going to get to add a hidden property, because I don't know how I refer to it, but I guess that might be.

Learn Straight from the Experts Who Shape the Modern Web

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