Check out a free preview of the full Advanced JS Fundamentals to jQuery & Pure DOM Scripting course:
The "Exercise 3: Solution" Lesson is part of the full, Advanced JS Fundamentals to jQuery & Pure DOM Scripting course featured in this preview video. Here's what you'd learn in this lesson:

Alexis walks through the solutions to exercise 3. During the explanation, Justin joins him to diagram what is happening in memory with the DOTCALL method.

Get Unlimited Access Now

Transcript from the "Exercise 3: Solution" Lesson

>> [MUSIC]

>> Alexis Abril: So let's walk through this. How many people solved it, by the way? Did anyone get through it? Kind of one? I know one did, somebody was talking about which type error do I throw? All right, you're getting really, really deep in there now. Okay, so the first thing we need to do, if we're talking about, let me show the exercise real quick.

[00:00:21] If we're talking about finding or invoking a method with a specified context, the first thing we need to do is find a reference to what we're looking for. I love the question that initially popped out in the chasse, can we use our prior method? Totally, we can totally do that.

[00:00:38] So I'm gonna call this fn in my example. And I'm gonna say DOT(obj, prop);. It turns out we just wrote a method. So walk up the proto chain and find a reference to a property. So this will go through obj and its entire proto chain looking for prop and return a reference if one is found.

[00:01:00] So in the next case we can just say, if something is found, I mean if you wanna get really deep into it there's gonna be better checks. I just want to say if something is returned, if we actually have a reference to something, then invoke it. So you could.

[00:01:17] This is the first place you would maybe, things would go like okay now we need to call the method. But this doesn't, there's a couple things wrong with this. One, ours is going to come in as, in our test case, this is going to come in as an array.

[00:01:37] So maybe speak takes, in our test case, speak takes a string argument. But we can't just pass in args itself, because speak expects, this expects a string foo, not an array of strings. So this is a little, right off the bat, the signature's gonna be different. We can't just pass in args.

[00:02:00] And the second problem with this is context, right? If we just invoke a function like fn openPrint, what is this going to be inside this function? What you guys think?
>> Speaker 2: Window?
>> Alexis Abril: Window? It is gonna be the window. Let's talk about the rules, DOT call, new keyword, and?

>> Speaker 3: Call and apply.
>> Alexis Abril: Call and apply. If this doesn't meet any of those rules, it's gonna be the window by default. So in this case it would just be the window. But one of the requirements we have and one of our rules really matches up nicely, right?

[00:02:38] We have a rule that says you need to invoke this function with a context that we specify. In terms about one of our rules, call apply, by definition, invokes a function of the context that we specify. So that's kinda nice. So we can do call() or apply(). Now these take different signatures, if you remember call() takes context and then arguments such as that.

[00:03:07] apply() takes context and then arguments such as that. For our usage here, what do you guys feel like we should be using, or what do you guys wanna use?
>> Speaker 3: apply().
>> Alexis Abril: apply(), cuz we have an array of arguments it turns out being passed in. That matches up really nicely too.

[00:03:23] It also might match up because we planned this exercise in advance. One of those two things, I'm not sure yet. So here we're gonna say obj, args. And we need to do one last thing for this particular exercise, what do you guys think that is? There's something still missing, but it's not always immediately obvious.

>> Speaker 2: We have to return it.
>> Alexis Abril: We have to return the value, we're invoke in the functions, cool, but we probably wants whatever value is coming out of that. So let's check this out, and boom. We have a passing test which is kind of nice. There's also a really nice way to illustrate how this works in memory, a couple of you guys have drawings on your notepads.

[00:04:09] But we'll have Justin come up here and show your really nice representation of what is actually going on behind the scenes.
>> Speaker 4: Thanks for suffering through that. Now I'm trying to explain it like kind of we do this a lot. Anyways, as we're training, we beat you over the heads with something hard, make you struggle, and I try to explain really good after.

[00:04:26] So I'm gonna try my best to explain at a high level what's going on cuz we just assembled a lot of different things we had just previously talked about. So again on a high level, what you were just trying to do, was implement, make it so that the DOTCALL operator, this person.speak(), actually works, right?

[00:04:46] So we're implementing that ourselves in JavaScript and that needs to look up a property in memory, of a function in memory, like the DOT operator does, and then call it. So let me draw what's going on in memory, and why this DOTCALL is doing what it's doing. So if here's our call object.

[00:05:09] We're creating a person object in memory.
>> Speaker 4: Let me know if-
>> Speaker 5: That's good.
>> Speaker 4: See it already? So here's person.
>> Speaker 4: So person is gonna point to a function and this is a prototype property.
>> Speaker 4: That points to an object in memory and then this has the speak property that points to another function memory.

[00:05:59] So here's that speak() function, I'm just gonna draw it like this, and I'm gonna make the speak property.
>> Speaker 4: That's what we've set up with the person prototype speak. Again, prototype is just like a normal property. We'll see how it's just like the dot operator uses the proto property, the new operator uses the prototype, we'll see that in a second.

[00:06:24] And then what's going to happen is it's going to do new person with Smith. What that's going to do is create a person instance in memory, who has it's proto property,
>> Speaker 4: Pointing to the person's prototype object. And this is gonna be lowercase person.
>> Speaker 4: Okay, so the DOTCALL operator is trying to do person.speak() and then call it with some arguments.

>> Speaker 4: Is your computer here? Can I escape out [INAUDIBLE]?
>> Alexis Abril: Hit escape, it'll get you out. Now hit command tab.
>> Alexis Abril: Hit command tab until you get to slide one.
>> Speaker 4: Okay, so,
>> Speaker 4: Actually, where do I get this test right here?
>> Speaker 4: Okay, here's the, that is smaller,

>> Speaker 4: So, quick, okay, so we created this Person. We had that person, and it is a speak() function and things like that. What would happen if I called a Person.prototype.speak()? And I called it with, make sure its the same up here. I'm just gonna copy this function over again which is okay to do, so you can see function and what I'm doing in the same place.

[00:08:20] If I called Person.prototype.speak() like this and I did,
>> Speaker 4: Alexis, what would this return?
>> Speaker 4: Anybody?
>> Speaker 4: Anybody confused about this? Like, what I mean that the fact that I can call it like this, right? All I'm doing is this Person.prototype.speak(), calling it as a function.
>> Speaker 6: But, isn't it in effect, a array?

>> Speaker 4: Not, speak is not, it's just expecting a to whom.
>> Speaker 6: Okay. It'd be, hello Alexis, my name is undefined.
>> Speaker 4: My name is undefined, exactly. Because this is going to be what?
>> Speaker 6: Referring to the window?
>> Speaker 4: Good guess-
>> Speaker 6: Prototype?
>> Speaker 4: But it's actually referring the prototype object, cuz remember the DOTCALL operator always uses what's left of the rightmost dot as this, right?

[00:09:42] So in this case it's going to be, you can still say undefined but this is gonna be a person.prototype. Now let's say I changed it around a little bit, I did var speak equals that. Now if I were to all speak like this. Now what would this return and what will this be inside this function?

>> Speaker 4: What? Well sorry. Yeah, my bad, sorry. That is what I meant to do. So I just set a variables speak equal to Person.prototype.speak, and I'm just calling it. What would this be?
>> Speaker 6: Window?
>> Speaker 4: Window, you're exactly right. And what would name be?. If we were to write this.main.

>> Speaker 6: Undefined.
>> Speaker 4: Probably it's actually made an empty strings just because windows name property defaults to an empty string. Okay so that's a little quick recap of the dot operator and how it supposed to work, right? DOTCALL is supposed to take what's on the left-hand side. Now the reason why this code is the way it is,

>> Speaker 4: It's like this. So the reason why this code is the way it is, is it's going to person and it's trying to find a speak value. So we're using using the dot operator we already created which is gonna go look for dot. Sorry, look for a speak property on person.

[00:11:27] It's not gonna have it. You're going to walk up the proto chain, find the speak() function and just return that function as a fact. So we'll just have floating this function. It doesn't know at all about this person, because functions really don't have any, it's all about how functions are called not about how they're defined, so we force the issue.

[00:11:50] We kinda force it, so that we're going to call this function, so person is what this is. That's basically another recap. Does that make sense, hopefully a little bit better now? Kinda see the bigger picture? And one thing I can say is this person object here has a name, which was I don't remember in our example, something thought was in, we already did an example.

>> Speaker 6: Alexis?
>> Speaker 4: Alexis.
>> Speaker 4: Cool, so, hopefully that makes sense, the bigger picture, hopefully you can start. Our whole goal for this is that you guys can start seeing a code. First you construct your functions, things like that. The DOTCALLl operator and kinda see what it's doing in this memory diagram.

[00:12:37] Thanks, sorry for interrupting.
>> Alexis Abril: Your good. [LAUGH]
>> Alexis Abril: Feel free if you have any questions at all, even if it comes to you a little bit later today, let us know. This is hard, this is really hard if you're coming from a statically typed language or like a Java.

[00:12:58] Cuz all the constructs, all the rules. JavaScript has a very simple set of rules, but they're very different from Java. So cool, all right. Okay,
>> Alexis Abril: So in summary we're gonna go through something very similar to this diagram. If we have var d = new Date() we have a new instance of Date.

[00:13:25] = bar, d.hasOwnProperty, where all these methods and properties are are gonna live is something like this. We have a d pointer pointing to our new objects which is the date. It going to assign, we have a foo pointer. This is actually a pointer or a foo pointing to a primitive string called bar.

[00:13:46] It's not gonna to have hasOwnProperty() here, it's gonna have to keep going up for our date prototype. This is because we've created a new Date, var objects protos gonna point to the prototype of our constructor, which is Date. It has things like it getDay and other methods. It's not gonna to find it there.

[00:14:07] So it's gonna keep going up to the base object. Keep going up to the base object to look for things up here, and this is where it's going to find something like hasOwnProperty(), and then it's going to do the same thing. We just went over here invoke it with that context.

[00:14:24] It's got it, and we are good.