FREELessons: 24Length: 1.8 hours

Next lesson playing in 5 seconds

  • Overview
  • Transcript

1.3 Backbone Classes

If you've used a JavaScript for a while, you know that JavaScript doesn't have actual classes. However, we can create constructor functions with prototypes that gives us a kind of class-like functionality, and Backbone has an interesting way of implementing this system. And it's used for each of the different components that we have in backbone, collections, models, views, and routers actually, as well. And, so I thought we would take a quick look at this class system before we begin looking at the individual components. And what I'm gonna show you here would be the same for each one of the different components in Backbone, however we're going to use models as our example. So the way you create a new model in Backbone, is by creating a new variable, so we'll just call this Model1, and you do Backbone.Model with a capital M, dot extend, and this function, here, takes an object as its parameter, and you could just use backbone.model as your class, however that is just the basic model class. It's more of an abstract class that your expected to implement. So we're gonna go ahead and create our own class Model1. And when you extend this model, you can give this a bunch of properties or methods, most of which we'll look at over the course of these lessons. The interesting thing that I want to talk about in this screencast is the constructor function for this class. Because normally when you create a constructor function in JavaScript, you do something like var Person = function. And, this function here, will do something, of course, to set up a person. And then later you'll say, new Person, like this. Right? And, so, you have this function that's being called when you say new. However, when we're creating a Backbone class and we say var m1 = new Model1, like this, what function exactly is gonna be called when we say we want a new Model1? Well inside this class, there's going to be called a function called constructor, which will be run to do some set-up of the model behind the scenes. And we will look at this in backbone in just a second. However, if we have any behavior that we want to run when a model is created, maybe event handlers, or something like that, what we will do is create a function that's called initialize. And in models the initialize function gets the attributes and any options that are passed in when you create that model. Anything we do in this initialized function will be done when the model is created. So I can say console.log created an instance of model one, and then down here when we create model one like this,you'll be able to see that we actually get this model. Now lets give this Model1 a property, so I'll say name equals, we'll just call it m1, and so then, after this, let's do a console .log. We'll say m1.get, and we will ask it to get it's name attribute. Although we haven't looked this yet, this is the method for assigning initial attributes when creating a model instance, and then we can get those attributes using the get method and passing the key name as a strain. I'm gonna load this up in the browser. I just have a very simple index.html file here. We are loading jQuery and underscore. Underscore is the only hard component of Backbone, however jQuery is usually a good idea, because some of the Backbone view functionality we'll use jQuery behind the scenes. And then of course we have our app.js files. So that's very basic. Now if I refresh this browser page here, you can see that we have two lines that have been logged to the console. First we've created our instance of Model1, and this was called when that initialized function was run. And then we also have m1, which is our name here, and I could make that a little clearer if I just say name. And there, you can see that this is the name of the Model1 instance that we created. And so, this is the methodology that you're going to use 95 or greater percent of the time, when you're creating any Backbone component, a Backbone model, view, collection, rotor. You're gonna use this initialize function most of the time. However, what you can do instead, and let's do this with a class that we'll call Model2, is instead of creating a function called initialize you create a function called constructor. Now, remember, the Backbone.Model class has its own constructor function, which is doing some work behind the scenes, including calling this initialize function. However, if you want to do something completely custom, you can override that entirely and in this function, I'll just console.log created an instance of Model2 via constructor. And let's go ahead, and I'm just actually gonna copy these two lines that we have for m1, and I'll go ahead and change them. And, I want you to notice what's going to happen here. We've created our Model2, we're creating an instance in Model2 and then, just logging out the name for Model2. If I refresh this, notice that we have an error. So first we have our Model1 stuff from last time. That's fine. Then we have created an instance of Model2 via constructor. And then we have this error, cannot read property name of undefined. The problem here is that the default constructor function is doing more than just calling this initialize function. It's actually setting up our attributes. So, when we pass in this attributes object right here, which you can see is actually this first parameter right here, Adders, the default implementation of constructor actually takes all of the values in here and makes them properties of the model instance that's being created. However, since we're no longer doing that, our m2 instance doesn't have a name. If you go to Backbone's website, right here in the top left corner, you can see a link to annotated source. And this is really neat. You can actually read through the entire Backbone source in kind of a pretty format, with all of the code on the right, and all of the comments on the left. And this can be really, really handy. I do recommend you take a read through this. You can actually learn a lot about JavaScript. What I wanna show you here is I'm just going to search for BACKBONE.MODEL right here. Okay, this is the function that is being called when we create a new Backbone model. And, of course, there are comparable function for view collection and router. You can see here, it has those attributes and options. And if you read through pretty much all of this code right here. This is just setting up the attributes of the model. And part of what this is doing is assigning those attributes, so that we can, later on, use get to access them. And then notice right at the bottom here we have this.initialize, which would be whatever the initialized value for the prototype of this class is, .applyto this passing in those arguments. And so this is where our initialize function is called. Now, you might notice there's nothing here actually called constructor, so how do I know that this is being overridden when we create our own constructor? Well, if I search for the helper functions, which are a little further down, this is where we have this extend function which you can see right down here at the bottom model.extend, and all the other extends, is set to this extend function right here. And this can be a little bit tricky to read through, but if you look at this portion right here, we'll create this child variable, which is actually a constructor function if the protoProps exists and has a constructor property. Now protoProps is the first property that's being passed to this extend function which means we have our extend function right here. The first object here, that is the protoprops object. And if it has a constructor property, then we set child equal to that constructor property. Otherwise we just return parent.apply, parent here being the parent class, which in case, would be Backbone.model. Right? So, Backbone.model, which is that function we just looked at earlier .apply, applying it to the object we're creating and the arguments that are passed in to this function right here. So basically, what this is saying is you're creating a new class that will either call the constructor function of its parent or will call the new constructor that you passed in instead. One more thing I want to point out is that each one of these classes that we create can be extended to create its own subclass. And sometimes you will want to do that. I've definitely had scenarios where I've had subclasses where I've created one view and then created subclasses of those views, so that I can reuse methods, and it's really made the logic, and actually just the length of the code, much, much simpler. Let's give a try to this. If I say backbone Model3, and let's start by doing Model1.extend. And I'm just gonna copy this initialize function that we have for Model1, and I'll just change this to say Model3. Now we're actually gonna have to get rid of our Model2 here. Actually, let's just change it to a Model3. There we go. So let's see if this works now. If we come back to the browser, and refresh the page. You can see pretty much exactly what you would expect. We created our instance of Model3, and then named it. So the interesting to note here is that with initialize, when you extend a class, remember the constructor of that parent class will be used. With Model1, the constructor is the default constructor, which we'll call the initialize function of the prototype, which in this case is Model3. So when you extend a function like this, it doesn't call the initialized function of it's parent class by default. However, backbone does give you access to those methods. If you look back here at this extend function, you can see right down here we have child.__super__equalsparent.prototype which gives us access to those methods. So within here I could say Model3___super__initialize. I could do something like .apply and apply it to this with the arguments that are passed in here. And now, when I refresh the page here, notice that to create our Model3, the initialize method of both Model1 and Model3 were called, so this double underscore super property may come in handy in that way. Another thing to note is that if I switch this to use Model2 as the parent, then if I refresh the page here notice that now it says we created a Model2 instance and we can't read property of name. And of course, this should make sense to you. Remember when we use extend here, it will default to using the parent constructor function, not the parent's initialize function. And so when we wanna use the parent's constructor function, we no longer have access to those properties, thus causing our error. So this has been a quick lesson on how the backbone of class functionality works, and now that you understand this, let's start looking at some of the actual Backbone classes.

Back to the top