This course is out of date and does not reflect Frontend Masters current standards. We now recommend you take the JavaScript: The Hard Parts course.
Transcript from the "Exercise 2: Solution" Lesson
[00:00:00]
>> Alexis Abril: [SOUND] This is one of those exercises, where if you're just shown the answer to it's really, really simple and it's just like, this just makes sense. But when you're exposed to this for the first time or if you're working in a language, maybe you're not familiar with all the constructs, this is a really, really good type of exercise to understand everything that's going on.
[00:00:21] So let's walk through how this actually works.
>> Alexis Abril: So, let me close this.
>> Alexis Abril: Okay, so we're gonna have, let me open my test page as well, this is over here, JS tests. All right, got my console and we got our failing tests, so I'm just gonna rerun this one single test over and over.
[00:00:53] Okay, so this is the test we wannna make sure passes. So the first thing we wanna check is if our current object actually has that property we're looking for. If we have it right then, then we don't need to go anywhere, we can just return it to immediately.
[00:01:10] So right off the bat, we can say if obj.hasOwnProperty (prop), then return it, and then otherwise keep walking up proto change. It's always good to verbalize what you're actually trying to construct cuz once you verbalize it, once you can get in this kind of pseudo setup, finding out the syntax to make sure you can access or in things actually, it just comes a little bit more naturally.
[00:01:45] So right off the bat, if our object that we're currently on, so if person has a name, in which our case it does, just return it off the bat. Now this trips people up a lot because maybe we're not familiar right off the bat with JavaScript being a dynamic language, this is still sinking in, so you might be inclined to do this first, and this is okay.
[00:02:09] This is actually really common. What this is gonna do, though, is it's gonna look for specifically the prop, like P-R-O-P, property of OBJ, which in our case isn't gonna exist for any of this. What we want is the value of prop. So we're gonna use our bracket notation.
[00:02:30] This will look for any parameter that we pass in, so this will return person and name if that's what we're passing it in our case. Otherwise, keep walking up the proto chain. There's a couple ways to do this, you could do this with a loop. Although, I've seen less and less people even go that route these days, which is nice.
[00:02:48] We're just gonna recurse up, so I'm gonna say else. And then we want to invoke our function that's the first step, right? We know we wanna do at least that much. We wanna call ourselves again, except with obj to walk up the proto chain, all we wanna do is call it's proto and then pass the same prop.
[00:03:13] This is going to keep looking up and up and up every proto's pointer until it finds an object that satisfies the first condition. And then it's gonna return it. Now this at face value like, we're accomplishing all the test's goals. So let me save this file. We're gonna go over to our test, and refresh and it still fails, and this is the weird part.
[00:03:41] Well, this isn't the weird part, this is the part where, anytime you're dealing with a recursive function, you might get lost in where you actually are. So let's step through this and figure out what this problem is. There you are. I'm gonna make this smaller so I can see it first.
[00:04:03] Sources, okay, blow this up a little bit. Okay, I can do that and we'll do this, okay. So the first time we come through here, I think for our tests, let me see what we're doing in our tests. Yeah, we're doing person with species and speak. So it's not name in our case, we have a name on the constructor, on the instance.
[00:04:37] So the first thing that's gonna come through is obj and prop. So the first things that are gonna come through when we step into this is we're gonna have our instance of a person which'll have a name of Alexis and the prop that we wanna look for which is species.
[00:05:00] Now you can see immediately right off the bat that this property doesn't exist on the current object, we'll have to look for it somewhere. So we're gonna step through. So the first condition fails cuz the object we were on did not have it. So we're recurse up with our object's proto and the same property we're gonna look for.
[00:05:21] So let's step into this. Now we are at the second level of this .call. We're gonna say does this object, you can see it over here on the right. Does this object have a species property? And it does. This is gonna pass. So we've passed our if statement, so we're gonna return OBJ prop.
[00:05:46] But here's the trick. It's gonna return to the DOT function that called it. Oops. It's not gonna return all the way to the front which is right here. It's not gonna return to the initial invocation of it. It's gonna return just one level up. So, here we need to make sure we return what the recursive call is doing and then if I turn this breakpoint off, play, and now our test passes.
[00:06:29] We're able to go all the way up the proto chain, find our species property in this scenario, return it to the .call object that initially invoked that recursive step, and then returned that function's gonna return all the way to our test case.
>> Alexis Abril: Right there. Does that make sense?
[00:07:03] Let me put up the answer while I talk about that. Now there is a case of, a couple people stumbled on it. What if nothing has this? So there is the case of walking all the way up to where it's gonna be null. So here if we were really doing this, we should probably do something like if obj.proto and then the actual else case would just be return undefined for catching all scenarios.
[00:07:38]
>> Speaker 2: But you don't have to put undefined.
>> Alexis Abril: Yeah, that's true. You could just do this, an empty function will return undefined.
>> Alexis Abril: Does that make sense? Does this part make sense, I really kinda glossed over that. But if you have a function that doesn't return anything versus a function that's explicitly returning undefined, you don't have to explicitly do this part.
[00:08:02] That was just for maybe an explicit on a set of slides.
>> Alexis Abril: Any questions over this? It's relatively simple when you write it out. It's only a few lines of code. But it's actually covering a very different concept. I don't wanna say complex cuz it's actually a pretty simple concept.
[00:08:27] But if you're coming from a statically type or a classical base language, this is weird, this is very, very different. Talking about protos and pointers and prototypes, it gets a little weird.
>> Alexis Abril: Cool? Okay, oops.
>> Speaker 2: There's a few questions.
>> Alexis Abril: Yes, where are we in the questions here?
[00:09:00]
>> Speaker 2: Can you call the function recursively with this call?
>> Alexis Abril: With this call?
>> Speaker 2: I'm assuming they just mean the call operator but I would say that you could use a call operator called dot dot call, but the dot function actually doesn't use the keyword this. So there's no reason for doing that.
[00:09:22]
>> Alexis Abril: If you wanted to set context within dot, yeah. But we're about to touch DOT call here in a second. So that's gonna maybe clear some of that up, so. Any questions on this so far? This is just walking up the proto chain and finding a property we're looking for somewhere on that chain.
[00:09:44] That's all this method is doing. That's all DOT does on its own.
>> Speaker 2: One thing to mention is just JavaScript is a language of convention. The proto properly on an object is really just like every other property. I put up a foo property on an object. That's just like putting a proto property on the object.
[00:10:02] The only difference is that the DOT operator magically just is programmed to look at the proto property. And just keep the walking proto property. That's it, it's just a normal property called something weird and the dot operator works with it to find stuff, it's that simple. It's just conventions.
[00:10:26]
>> Alexis Abril: I like that, it's a good way to explain that.
>> Alexis Abril: Cool, okay, so if it hasn't gotten weird enough, let's take this a little step further. We were just talking about context and we were talking about what this could be in a certain set of situations. And we said, remember, one of our rules, do you guys remember our three rules for setting context?
[00:10:55] Can anyone give me the three rules? Any one of the three rules? Or four rules, there's a base rule, too. How do you set this? What are those rules, anybody?
>> Speaker 3: New.
>> Alexis Abril: The new keyword. That's one rule. Good. Any others?
>> Speaker 4: Call function.
>> Speaker 3: Call apply.
>> Alexis Abril: Call and apply, if you just call the function, what is it gonna be?
[00:11:23]
>> Speaker 4: The window.
>> Alexis Abril: It's gonna be the window, that's the base case and what's the last rule?
>> Speaker 3: Dot-
>> Alexis Abril: DOT call, yeah, DOT and then invoking a function. Exactly. DOT call is one of our rules and it will set context to whatever's left of the dots. Okay, that's a really.
[00:11:42] Yes, question?
>> Speaker 2: Real quick, somebody's asking, can you just show where you're debugging in Chrome, can you just show how you were doing that?
>> Alexis Abril: Yeah, so these are Chrome's dev tools. I'm always on the side of use whatever browser you're most comfortable with. Just please make it a modern browser.
[00:12:03] I use Chrome, I'm very comfortable the dev tools. A lot of the guys on the team or mostly guys in the team are either Chrome or Firefox. Both have really, really good sets of devs tools. And the other browsers have really, really come a long way too. But for this, this is really really nice.
[00:12:16] I pop open a console, I'm doing this from sources. If you go to the sources tab, you can see all the scripts. All of the resources, you can see on the left side a folder structure, this is everything that this page is requesting. So in our case, we're requesting an H.T.M.L. file, that's the page you see.
[00:12:36] And we're requesting a J.S. file, that's what's actually running our tests against. You might just explain how you got that up. Yeah, on a Mac, or you can go to over here the little hamburger icon, and you can go down to More tools, thank you, and Developer tools, any one of these will open a particular subsection.
[00:12:59] If you're on a Mac, I just press Cmd+Option+I cuz I have it memorized. I forgot where it was in the menu for a second. And I think Cmd+Option+I will actually open Firefox as well. I'm pretty sure the same shortcuts, everybody's doing the same shortcuts these days. This'll open this up, then you can actually click on the file.
[00:13:18] This is nice cuz if you're familiar with C# and Java, being able to step through is really nice. So these browsers make this part really easy when you wanna see what's going on. So you can add a breakpoint, all I did was add a breakpoint over here, you can add a bunch.
[00:13:33] They'll show up over here, you can see breakpoints, you can disable them which is nice. And then I added a few watch expressions. I'm watching for the O.B.J. and the prop variables. You'll notice they're not available at the moment, because we're not in the context of running our page.
[00:13:50] So, those only exist because we have them wrapped in a closure, and at the time of running, you'll see what that evaluates to. So, if we were to just run this again, and I enabled breakpoints, we can see at the time of this function's evocation, I can see, hey, the person is this, like this, on the screen.
[00:14:09] And prop is species. Which is really, really nice, especially if you're dealing with loops or recursive or just a lot of modules, or a lot of JavaScript on the page, you wanna see what exactly it is. Because as a human, it's really hard to interpret a wall of just text and know what the output is.
[00:14:26] You want to be able to step through and see, i is not being reassigned, that's the problem, immediately. So, this is how we do all that. And then you can step through, step over, just like most debuggers and then play to get out.
>> Alexis Abril: Which is nice. So familiarize yourself, Chrome or Firefox, I think have the two most comfortable sets of dev tools, but they're all getting pretty good these days.
[00:14:57] They're all getting better.