Introduction to Object Oriented Programming
Objectives
-
Define what OOP (Object Oriented Programming) is
-
Revisit the 'new' keyword and understand the four things it does
-
Use constructor functions to reduce duplication in our code
-
Use call and apply to refactor constructor functions
OOP Defined
-
A programming model based around the idea of objects
-
These objects are constructed from what are called "classes", which we can think of like a blueprint. We call these objects created from classes "instances"
-
We strive to make our classes abstract and modular
OOP in JavaScript
But JavaScript does not have "classes" built into it - so what do we do?
We use functions and objects!
Object Creation
var house = {
bedrooms: 2,
bathrooms: 2
sqFeet: 1000
}
var house2 = {
bedrooms: 2,
bathrooms: 2
sqFeet: 1000
}
var house3 = {
bedrooms: 2,
bathrooms: 2
sqFeet: 1000
}
var house4 = {
bedrooms: 2,
bathrooms: 2
sqFeet: 1000
}
// woof...imagine if we had to make 100 of these!
Imagine we want to make a few house objects, they will all have bedrooms, bathrooms, and numSqft
A Solution
Instead of making an infinite number of different objects, let's see if we can create a function to construct these similar "house" objects.
Constructor Functions
function House(bedrooms, bathrooms, numSqft){
this.bedrooms = bedrooms;
this.bathrooms = bathrooms;
this.numSqft = numSqft;
}
Let's use a function as a blueprint for what each house should be - we call these kinds of functions "constructor" functions
- Capitalization of the function name - this is convention!
- The keyword 'this' is back!
- We are attaching properties onto the keyword 'this'. We would like the keyword 'this' to refer to the object we will create from our constructor function, how might we do that?
Notice a few things...
Creating an object
function House(bedrooms, bathrooms, numSqft){
this.bedrooms = bedrooms;
this.bathrooms = bathrooms;
this.numSqft = numSqft;
}
So how do we use our constructor to actually construct objects?
- We are not returning anything from the function so our House function returns undefined
- We are not explicitly binding the keyword 'this' or placing it inside a declared object. This means the value of the keyword 'this' will be the global object, which is not what we want!
var firstHouse = House(2,2,1000) // does this work?
firstHouse // undefined...guess not!
Why is this not working??
The 'new' keyword
function House(bedrooms, bathrooms, numSqft){
this.bedrooms = bedrooms;
this.bathrooms = bathrooms;
this.numSqft = numSqft;
}
Our solution to the problem!
- It first creates an empty object
- It then sets the keyword 'this' to be that empty object
- It adds the line `return this` to the end of the function, which follows it
- It adds a property onto the empty object called "__proto__", which links the prototype property on the constructor function to the empty object (more on this later)
var firstHouse = new House(2,2,1000)
firstHouse.bedrooms // 2
firstHouse.bathrooms // 2
firstHouse.numSqft // 1000
So what does the new keyword do? A lot more than we might think...
Your turn!
Create a constructor function for a Dog - each dog should have a name and an age. As a bonus, add a function for each dog called 'bark', which console.log's the name of the dog added to the string 'just barked!'
// Your constructor function goes here
// this code should work if you have implemented it correctly
var rusty = new Dog('Rusty', 3);
var fido = new Dog('Fido', 1);
rusty.bark() // Rusty just barked!
fido.bark() // Fido just barked!
Solution
// Your constructor function goes here
function Dog(name, age){
this.name = name;
this.age = age;
this.bark = function(){
console.log(this.name + " just barked!");
}
}
var rusty = new Dog('Rusty', 3);
var fido = new Dog('Fido', 1);
rusty.bark() // Rusty just barked!
fido.bark() // Fido just barked!
We can add methods to our objects inside of the constructor function
Multiple Constructors
function Car(make, model, year){
this.make = make;
this.model = model;
this.year = year;
// we can also set properties on the keyword this
// that are preset values
this.numWheels = 4;
}
function Motorcycle(make, model, year){
this.make = make;
this.model = model;
this.year = year;
this.numWheels = 2;
}
Let's create two constructor functions, one for a Car and one for a Motorcycle - here is what it might look like
Notice how much duplication is going on in the Motorcycle function. Is there any way to "borrow" the Car function and invoke it inside the Motorcycle function?
Using call/apply
We can refactor our code quite a bit using call + apply
function Car(make, model, year){
this.make = make;
this.model = model;
this.year = year;
// we can also set properties on the keyword this
// that are preset values
this.numWheels = 4;
}
function Motorcycle(make, model, year){
// using call
Car.call(this, make, model, year)
this.numWheels = 2;
}
function Motorcycle(make, model, year){
// using apply
Car.apply(this, [make,model,year]);
this.numWheels = 2;
}
function Motorcycle(make, model, year){
// even better using apply with arguments
Car.apply(this, arguments);
this.numWheels = 2;
}
Recap
-
Object Oriented Programming is a model based on objects constructed from a blueprint. We use OOP to write more modular and shareable code
-
In languages that have built-in support for OOP, we call these blueprints "classes" and the objects created from them "instances"
-
Since we do not have built-in class support in JavaScript, we mimic classes by using functions. These constructor functions create objects through the use of the new keyword
-
We can avoid duplication in multiple constructor functions by using call or apply
Introduction to Object Oriented Programming
By Elie Schoppik
Introduction to Object Oriented Programming
An introduction to Object Oriented Programming in JavaScript
- 1,741