Advanced JS Fundamentals to jQuery & Pure DOM Scripting Exercise 12: Solution
Transcript from the "Exercise 12: Solution" Lesson
>> Justin Meyer: So I'm gonna kind of go through again why we're doing it like why we're doing what we're doing. Hopefully most of you have used jQuery at some point. And if you're used to jQuery, you do something like this, if I wanna get every li in the page.
[00:00:20] I can do var lis = $li and then I can do something like this and go lis
 and that will actually give me the li element. All right, and I can do lis.length and that will give me the number of lis in the page. What you're doing fundamentally when you do $li like this, is you're really making an instance of jQuery, underneath the hood that's what's happening.
[00:00:55] And we're going to make ours work pretty much the exact same way as jQuery. But we're starting with instead of just being able call dollar like that we're starting with it, so you have to call new dollar. But we want the same behavior, we want it so you get a list of lis.
[00:01:15] You get a list of lis back and there's also by the way, I forgot to mention the one other important thing. This lis has all the jQuery methods you've come to love and adore which is like the HTML method. That will give you the HTML of the first li in this collection.
[00:01:31] Maybe it was like Hello, World or something like that, right? So what we want is a constructor function dollar that returns to us an instance of something that has all of these HTML and text methods and stuff like that, that we're adding to $prototype. So we have all of these methods here, but at the same time, it looks like an array, right?
[00:02:02] It's got a length and it has items, kind of numeric properties so it looks just like an array but it's got all these methods and this is really the secret of jQuery. In a lot of ways it hit a lot of things right, it was like an array, but had all these useful methods.
[00:02:22] It had chaining and all this other nice stuff that made it super useful. That's why it's so popular today. Any questions with that before I go onto the solution?
>> Justin Meyer: Okay, so, we wanna get something like this working, and we're passing in a CSS selector. So, first thing I'm gonna do is, I will make an elements array, get elements from the page that match the CSS selector.
[00:02:54] So we document.querySelectorAll, and I'm gonna pass it the selector that was passed in. So if li was passed in, document.querySelectorAll is gonna give me an array of elements, array of lis, something array like that lis. Now here is the really tricky hard part, is you need to make it so that whenever new$ is called, this is going to be an instance of $.
[00:03:28] The only way I can really express that is by doing this.__proto__ === $.prototype or I guess I could write it also, this is an instanceof $. So this will already have, I can already write in here. I could write this.html and that would work. Well, it would exist and it would call an empty function right now.
[00:03:59] What I want to be able to do is make sure it has a this
 property. And I also wanna make sure it has a this.length property, this
 is gonna be just like that li up there. And this.length would be the number of lis in the page, maybe five.
[00:04:15] So I want all of this behavior that jQuery adds. The way to do this, the easiest kind of way I think to understand is just brute force, copy every element in here onto a numeric property of this. So I'm gonna do just that, I'm gonna go through every element,
>> Justin Meyer: And I'm going to set this[i] so I'm going to set a numeric property. So I'm gonna set this .zero essentially equal to elements i.
>> Justin Meyer: Guys with me there? All right, awesome. And then I wanna make sure has this length property, so I'm gonna do this.length = elements.length,
>> Justin Meyer: Cool, so some of you might remember there is this hint that I said that can make,
>> Justin Meyer: Make this kind of code go away because there's a nicer way of doing it. The hint is to use push and steal it for our own purposes. So instead of doing all of this, I could, I'll do it above it and delete it.
[00:06:03] I could get array, well, if I want to shorthand for getting array.push I can write it like that. Or I could write Array.prototype.push, but instead of making this a normal array. Instead of push operating on a normal array, I can make it operate on this and pass it the elements.
[00:06:30] And Array.push pushes code, pretty much looks the exact same as, looks pretty similar to this. So it really just does the same thing and this is a way of saving some code, and maybe performing a little bit better too. Any questions about that and this trick? You'll see this kind of thing reaching out to array's prototype methods on things that are not arrays all the time.
[00:06:58] If you ever open the hoods to any open source library.
>> Speaker 2: Should be applied since its element is-
>> Justin Meyer: It should be applied, thank you. I wrote that wrong.
>> Justin Meyer: And we might even have to make, in some browsers I think you have to even do then, $.makeArray, but you don't give them.
>> Speaker 3: In older [INAUDIBLE] then you would have to do what you said.
>> Justin Meyer: Yeah, and you'd have to set the length property to zero to make it totally work in all browsers.
>> Speaker 3: Yeah.
>> Justin Meyer: But this, this works right here, any questions about this? So I'm gonna set it back to the other one, just so we can see what's going on.
[00:07:52] I'm going to step in to a debugger just to show what's happening here.
>> Justin Meyer: Oops, let me delete my code at the top of my page, it doesn't work, because I like going through a debugger with these things.
>> Justin Meyer: So is that code big enough hopefully, yeah, maybe?
[00:08:27] Okay, so we are gonna walk the call stack here. We just did, those move fast, new$ with contacts li.contacts. So this is gonna get every contact, that's an li inside of our contacts element, which these guys are all up in here, in the test fixture. So we're gonna do a document.querySelectorAll with the selector as contacts, li.contact.
[00:09:04] By the way one thing I wanna just mention You see here these scope variables? These things match, each one of these little, these are call objects, each one of these little arrows right here. And if you understand call objects, then you can understand what's going on and why this shows, because it has this inside of it.
[00:09:26] It has the elements and it has the selector arguments, and it also has the i which is currently on the find as well. And then if we walk up to the closure, now we're in the invocation of this function, this outer function that's immediately invoked. var isArrayLike is in there, and then if you keep walking up, you eventually get to the global call object which has everything in it, right?
[00:09:51] So we're just kind of walking up our call objects, so hopefully now if there's one thing you can take away from this. It's that you now understand completely what these things are and how they relate to closures. So back to this, we saw that it was selector, it was called with a selector.
[00:10:14] I'm gonna step over, I'm gonna kill all this stuff, hide that, shown here. We'll see that elements is a node list, so not a true array, but sure acts very similar to one. It's got each liin it, and then we're gonna simply, we'll see what our this is.
[00:10:35] You could see the prototype methods on a proto. And we're all going to see, just added a zero property which is the first contact. That's gonna add a 1 property and then it's gonna add a length as 2. So this is what our $ looks like in memory, it's got a 0, 1 in length property and it's got a proto property that points to the $prototype function.
>> Justin Meyer: Cool, so also hopefully, I hope that connections are starting to be made even with debugging tools and things like that. To me it's awesome that if you understood yesterday's stuff you can kind of get what's going on in here. Why is that proto and why are these things there?
[00:11:23] Now it might make sense, okay.