Just like the Array
, Date
, and RegExp
object types, Javascript allows you to define your own object types for re-use with the new keyword.
We do this by defining a "constructor" function:
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = firstName + ' ' + lastName;
}
By convention, constructor functions start with an uppercase letter.
Then we can create new objects of our custom type using the new
keyword, just like with Date
s or any of the other built-in types.
var dad = new Person('Brandon', 'Carpenter');
var baby = new Person('Genevieve', 'Carpenter');
log( dad.fullName );
Constructor functions have a "special" variable named this
that JavaScript automatically creates for you.
The value of the this
variable is the object that your constructor creates.
Here's another example:
var Person = function(name) {
this.name = name;
this.greet = function() {
var greeting = this.name + ' says Hello!';
alert(greeting);
};
}
var brandon = new Person('Brandon');
var kaiti = new Person('Kaitlin');
log( brandon.name );
log( kaiti.name );
brandon.greet();
kaiti.greet();
Writing custom type constructors gives you a few perks:
this
var, so in them you can use any properties that the constructor stored in this
.As you can probably tell, custom types are most useful if you are going to be dealing with a bunch of objects that have the same properties or methods.
var Todo = function(text, dueOn) {
this.text = text;
this.dueOn = new Date(dueOn);
this.render = function() {
var dateString = this.dueOn.toDateString();
var html = '<article>\n' +
' <h1>' + this.text + '</h1>\n' +
' <p>' + dateString + '</p>\n' +
'</article>';
return html;
}
}
var todo1 = new Todo('Take out the trash', '3/8/2013');
var todo2 = new Todo('Wash the dishes', '3/7/2013');
alert( todo1.render() );
alert( todo2.render() );
There's one more special feature of custom object types constructors. They have a built-in property called prototype
. Any properties or methods set on the prototype
property is automatically shared by all objects created by the constructor.
function Person(name) {
this.name = name;
}
Person.prototype = {
greet: function() {
var greeting = this.name + ' says Hello!';
alert(greeting);
}
};
var brandon = new Person('Brandon Carpenter');
var kaiti = new Person('Kaitlin Carpenter');
log( brandon.name );
log( kaiti.name );
brandon.greet();
Note that we're setting the prototype property on the constructor function, not the this
variable.
Here's how it works:
When you use the "." operator to get a property from an object, Javascript first checks to see if the object has that property.
If it doesn't, Javascript check's to see if the object's prototype has that property. If it does, Javascript will use that.
If it still doesn't, Javascript will check the prototype's prototype, etc.
Defining methods of object types using prototype instead of just assigning them to "this" within the constructor function has a few advantages:
Honestly, it doesn't really matter if you understand the distinction. Just know that whatever you assign to this
inside of the constructor is unique to that object, but anything you add to the constructor prototype is shared by all objects created using that constructor.
One word of warning. Inside of event listeners, JavaScript changes the value of this
to be the DOM element that triggered the event. So be careful if you try to do something like this:
// element is a jQuery object
var MyWidget = function(name, element) {
this.name = name;
element.click(this._handleClick);
}
MyWidget.prototype = {
_handleClick: function(e) {
e.preventDefault();
// The value of `this` is the element that
// was clicked instead of the object you
// created with the MyWidget constructor.
// So this doesn't really work.
alert( this.name );
}
}
var widget = new MyWidget('name', $('#testLink'));
There are a couple of (ugly) workarounds to this, as well as a standard (that isn't supported in IE versions < 9). Here are some links if you're interested:
My recommendation is to just avoid listening to events inside of your custom data types, and keep that code separated somewhere else.
At the core, OOP is just a way of organizing code.
The idea is to separate responsibilities of a program into individual components, which can be tested against individually, and define relationships between them to collaborate and get things done.
When it makes sense, people tend to create object types that correspond to real-world objects. The reasoning for this is that real-world objects automatically have constrained roles and responsibilities, and generally have a natural inheirtance structure as well.
When people talk about OOP, they generally refer to the following topics:
And to a lesser extent, these topics as well:
And these topics, which don't really exist in Javascript:
We don't have time to get into, but I'm listing them here for you to research after you're through with this class. Understanding these topics will help you communicate better with backend developers, and may even help you get a job.
Table of Contents | t |
---|---|
Exposé | ESC |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Notes | 2 |
Help | h |