6.8 KiB
Object Oriented Design in Javascript
Lesson Objectives
- Use JavaScript objects to model the real world
- Assign functions to variables and properties of objects
- Use methods to access properties of the object
- Use constructor functions to make creating multiple similar objects easy
- Create a base class which can be used to create child classes
- Use prototype to assign properties to a class
- Assign the correct prototype to a sub class
- Correctly assign the constructor of a child class
Use JavaScript objects to model the real world
Objects in javascript are just key/value pairs
var matt = {
age: 36,
eyes: 'blue',
name: 'Matt'
}
Can retrieve values using dot notation
matt.age //returns 36
Can modify an object's properties like so:
matt.age = 40;
matt.eyes = 'green';
Assign functions to variables and properties of objects
Functions are objects and can be assigned to variables
var myFunc = function(){
console.log('hi!');
}
myFunc();
Functions can be assigned to properties of objects. These functions are referred to as methods of the object. It's like having the object perform an action.
var matt = {
sayHello: function(){
console.log('Hello, my name is Matt!');
}
}
matt.sayHello();
Use methods to access properties of the object
When invoking methods, you can reference other properties of the object with the keyword this
var matt = {
name: 'Matt',
greet: function(){
console.log('Hello! My name is' + this.name);
}
}
matt.greet(); //logs 'Hello! My name is Matt'
Use constructor functions to make creating multiple similar objects easy
If you need to create multiple objects of the same type, object literals ({ property:'value'}) can be inefficient. We can create constructor functions, which act like a blueprint (or class) for creating objects.
var Person = function(){
this.numArms = 2; //use the this keyword to create properties and methods
this.numLegs = 2;
}
var me = new Person(); //use the new keyword to instantiate a new object
var someoneElse = new Person();
console.log(me);
console.log(someoneElse);
We can pass parameters into constructor functions to make instances unique
var Person = function(name){
this.name = name;
this.numArms = 2; //use the this keyword to create properties and methods
this.numLegs = 2;
}
var me = new Person('Matt'); //use the new keyword to instantiate a new object
var someoneElse = new Person('Joey Jo-Jo Junior Shabadoo');
console.log(me);
console.log(someoneElse);
Methods are added just like adding properties
var Person = function(name){
this.name = name;
this.numArms = 2; //use the this keyword to create properties and methods
this.numLegs = 2;
this.sayHello = function(){
console.log("Hello, my name is " + this.name);
}
}
var me = new Person('Matt'); //use the new keyword to instantiate a new object
me.sayHello();
Create a base class which can be used to create child classes
We can have a "class" inherit from another class, using the .call static method of a function
var Car = function(){
this.wheels = 4;
}
var Humvee = function(){
Car.call(this);
this.numAmericanFlags = 4;
}
var murica = new Humvee();
console.log(murica);
Use prototype to assign properties to a class
The problem with using this.wheels = 4 inside a constructor function is that the code runs each time you create a new object. This is redundant.
Instead we can assign the property to the function's .prototype property instead.
var Car = function(){
}
Car.prototype.wheels = 4;
var myCar = new Car();
console.log(myCar.wheels);
Car.prototype.wheels = 4;runs only once, but all instances of the Car class have the wheels property already set. You can do this with any property you want- If you do
console.log(myCar)you'll notice that you can inspect the prototype of the Class of the object by looking at the.__proto__property. There you'll find the .wheels property you added toCar.prototype - When you look for a property of an object, it will first look on the object itself, then on its prototype, then on the prototype's prototype, etc...
Assign the correct prototype to a sub class
If we are using prototype to add methods and properties to our class, our inheritance process gets a little tricky
var Person = function(){
}
Person.prototype.legs = 2;
Person.prototype.arms = 2;
var Student = function(){
Person.call(this);
}
var matt = new Student();
console.log(matt.legs); //returns undefined?!
To fix this, we need to assign a person object to the Student.prototype property
var Person = function(){
}
Person.prototype.legs = 2;
Person.prototype.arms = 2;
var Student = function(){
Person.call(this);
}
Student.prototype = Object.create(Person.prototype); //create a Person object, then assign it to the Student.prototype
var matt = new Student();
console.log(matt.legs); //returns 2
Now we've created a Person object and assigned it to the to Student's prototype property. Now when a Student object looks for .legs it will go to the Student's __proto__ (Person object) and then the __proto__ of that object.
Correctly assign the constructor of a child class
A good way to check a constructor is to log the .__proto__.constructor property:
var Person = function(){
console.log('constructing person');
}
Person.prototype.legs = 2;
Person.prototype.arms = 2;
var matt = new Person();
console.log(matt.__proto__.constructor);
This becomes a problem when doing inheritance:
var Person = function(){
this.foo = 'bar';
}
Person.prototype.legs = 2;
Person.prototype.arms = 2;
var Student = function(){
Person.call(this);
}
Student.prototype = Object.create(Person.prototype);
var matt = new Student();
console.log(matt.__proto__.constructor); //logs Person?!
This is because we are wiping out the normal constructor function when we reassign the prototype. To fix this, we need to add the constructor back in:
var Person = function(){
this.foo = 'bar';
}
Person.prototype.legs = 2;
Person.prototype.arms = 2;
var Student = function(){
Person.call(this);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student; //add the constructor back in to the prototype
var matt = new Student();
console.log(matt.__proto__.constructor);