Transcript from the "The Dot(.) Operator" Lesson
>> Alexis Abril: Let's talk about dot, the dot operator. Here we have, we're gonna visualize what this code is doing in memory as we set it up. So we talk about foo equals object. We're just creating a new object in memory. If you remember from our comparisons, curly brace double equals curly brace, we're creating two new objects in memory.
[00:00:25] So just using the curly brace syntax, we have a new object in memory and we're pointing the foo pointer to that new object. Then we gonna call foo.toString. Now instinctively we kind of know this is going to work, but our object is empty. There is no toString method, so how does it find, how does it invoke toString?
[00:00:49] We know this kind of stuff just exist in space, but it has to be wired up somehow. So what this is doing behind the scenes, as we have our foo pointer, which is pointing to our object in memory. We're creating,
>> Alexis Abril: We have our, thought that should have all come up at once.
[00:01:09] We have objects, when I say capital object, this object here, this is the base object that everything inherits from, which is a function. Object itself is just a pointer to this function in memory. This function, this is gonna lead a little bit. So hold on, we'll get through this.
[00:01:30] As a prototype property which points to an object in memory. Its proto will point to null, this is the base object. So if you've ever heard the term proto chaining, it's walking up its proto property to look for other properties. Don't worry, if this is a lot to digest, we're going to keep diving into this with prototype base inheritance.
[00:01:57] But, this is where toString lives. toString lives on the base objects prototype. Without getting too deep into prototype-based inheritance, you can think of, if you're familiar with the concept of classes. You can think of a class as the blueprint for all newly created objects. You can kind of think at a very abstract level, you can think of a prototype, as that same blueprint for all newly created objects.
[00:02:24] So this is the base objects blueprint, and it has a toString method. Then what we're doing, when we created our new object in memory, all we're doing is wiring up the proto chain. We're setting our objects proto property to the base object. All newly created objects have a proto property that point to the base object by default, because everything inherits from the base object.
[00:02:57] And this is how we find our toString method. We start at foo, we say foo.toString, we start at foo, it points to this object, and we say, hey do you have a toString function? This object doesn't have anything, so it walks up the proto chain to the next object.
[00:03:17] At the next object it says, hey do you have a toString function? It does, and it chooses to return and then invoke it, cuz we're calling it. If it didn't, it would walk up the proto again, hit null and just return undefined, we don't have anything. We've walked all the way up the proto chain, and we haven't found any property that you're looking for.
>> Alexis Abril: Once it finds it, it returns it, we're invoking it, so we're creating a new call object, and this this inside of this call object, is gonna point to the original object that we're calling it from, because we use the .call operator. So the left side of the dot is our foo object, so this, even though toString lives higher up the chain, context-wise, this is gonna to point to our foo objects.
>> Alexis Abril: Yes, question.
>> Speaker 2: There's a question on this, those in capital letters are concepts?
>> Alexis Abril: Are concepts, what purpose are you talking about, like prototype and objects?
>> Speaker 2: Yes.
>> Alexis Abril: Okay so prototype is actually a pointer. I think it was just in all caps for the style.
>> Speaker 2: It should be in lowercase.
>> Alexis Abril: Yeah, It should be all in lowercase.
>> Alexis Abril: All right, we'll just change that prototype, there we go.
>> Alexis Abril: Okay, our object is just wrapped to these circles. We could just use circles, I put a label on there, object, just to say what they are, but these are the actual objects in memory.
[00:05:07] Everything on top of a little arrow is a pointer.
>> Speaker 2: And there was a question [INAUDIBLE] this, when you're using this do, you have to always think about how you'll be calling the function in which you're using it?
>> Alexis Abril: Yes and that part is hard to say, because if you're providing an API,
>> Alexis Abril: You're still gonna have just like any arguments, you're gonna have expectations of how it's used, but you really wanna think of it just as, whoops.
>> Alexis Abril: You wanna think of any kind of function just in their own sandbox, I would think. Just like you're passing in arguments, you can do crazy things like pass in an object with a toString method, if you're familiar with that function.
[00:06:03] So you could do the same thing with this. If someone is familiar with a popular method like array.slice, we could override the context for our needs. That doesn't mean the author of the slice or splice methods on array should have been aware we're gonna do things. They would just expect this to be something that they expect.
[00:06:30] If that, I feel like I used too many nondescript words in the description.
>> Speaker 2: I would just say that you should, it's good to be aware of what you want, that what this should be here. Especially if you're using it, if people are using your API appropriately.
>> Alexis Abril: Yes.
>> Speaker 2: All right, and how that works, you should know. That's why we're training it, however, you don't have to guard against unexpected values of this. Like I could create a prototype function, something on a prototype of an object that uses this, calls, this.name or something like that. And I shouldn't have to check if this is actually an instance of my constructor function.
[00:07:16] Or maybe this is the Window, or this is something that I don't expect and throw an error or something like that. I don't think you need to write code like that. And you really, really shouldn't, but it's good to be aware of how this works.
>> Alexis Abril: Yes.
>> Speaker 2: So then you can steal it, and like steal functionality for other things, and kind of mix in behavior, we'll see how you can kind of exploit changing this.
[00:07:40] But you when you're writing code that talks to this, you shouldn't have to worry about.
>> Alexis Abril: I can name, really quickly, here we go without going too far into this.
>> Alexis Abril: When you're doing checks like that, when you're checking what this is and then executing some logic after.
[00:08:00] It actually, initially it might feel like it might make things simpler for users of your API. But at the end of the day, it creates a little bit of a confusion factor. So we're gonna see a couple examples of this, without giving too much away in the exercises we do.
[00:08:24] I'm not sure we're gonna get to it at the end of today, or tomorrow. Where we're gonna see that type of a check, where you're checking what this is, what it can be, and then going one way or branching one way or the other in logic to execute something in a function.
[00:08:39] That's a really abstract way to say, I agree with Justin, but there is a situation, a very popular situation where it's gonna be weird, so, okay.
>> Speaker 2: There's one more question on proto. Is proto the particular instance prototype, as opposed to the static objects prototype?
>> Alexis Abril: Is proto the particular instance?
[00:09:02] So, one way to remember protos and prototypes, because all this can get really, really confusing really quickly. From our perspective, from the consumers of the API's perspective, functions have prototypes. Objects have protos, it's an easy way to remember this. Functions have prototypes, objects have protos. Object's proto points to whatever it is inheriting from, this is the path it's gonna take as it walks up to look for properties or methods.
[00:09:37] A function's prototype is if you're gonna construct a new, like if you have a foo object, and we wanted to create a new, or a foo as a function or object, object's on there. If we wanted to say new object, we would look at the prototype object, and this is where we would point our new object's proto to.
[00:10:02] This is how we would set up our pseudo-inheritance. It's not true inheritance, it's just a way to look up properties and methods.