By the end of this lesson, students should be able to:
- Demonstrate a use case that explains prototypal inheritance and what kind of flexibility it gives to programmers
- Use namespaces to organize application code
- Define a custom constructor method that sets one or more properties of a new object
Before this lesson, students should already have experience with:
- Ruby and Ruby-based OOP
- Javascript variables, functions, objects and callbacks but not prototypes and constructors
Last year, I helped a friend prepare for his Christmas Bell workshop. He put together a complete set for me to follow as I packed the remaining 30 sets.
The 1st Christmas bell set that my friend put together is what we would call a prototype, which is what we are learning today.
You've learnt about Javascript objects in the previous lesson - objects have properties (I have something) and methods (I can do something).
Well, every Javascript object has/follow a prototype. The prototype is also an object, just like the prototype Christmas bell is a physical set like the rest and not just a drawing.
All Javascript objects inherit their properties and methods from their prototype. For the Christmas bells, if the prototype has a red ribbon, all of them will have red ribbons. If the prototype can light up, all of them can light up.
Let us implement a Christmas bell object in Javascript and give it these properties: name, ribbonColor. According to your previous lesson on objects, if we want 2 bells, the code would be:
// Create individual bells
var bell01 = {name:"Bell 01"};
var bell02 = {name:"Bell 02"};
// Let's add ribbons!
bell01.ribbonColor = "red";
bell02.ribbonColor = "red";
Imagine the above with 30 bells! What happens if we used prototypes?
// A constructor for bells - convenient!
function bell(name) {
this.name = name;
}
// Create individual bells
var bell01 = new bell("Bell 01");
var bell02 = new bell("Bell 02");
// Let's add ribbons!
bell.prototype.ribbonColor = "red";
Hmm...since the bells inherit from the bell prototype, does the bell prototype inherit from anything?
console.log(bell01.toString()); // [object Object] - where did this method come from??
// Override the toString() method from Object prototype, using a callback
bell.prototype.toString = function () {
return "I am a bell and my name is " + this.name + ".";
}
console.log(bell01.toString()); // I am a bell and my name is Bell 01.
There's more, but instead of me doing all the talking, it's your turn to think and exercise your fingers!
3 questions:
- What if we want all the bells to have a lightUp method, ie. bell01.lightUp()?
- The constructor now is a global function, which may easily be misused, eg. var cowBell = new bell("Cow Bell"). How do we fix that?
- Is there a way for us to set the ribbon color when creating the individual bells?
Type out your answers and test them! You can copy the code below to start off:
function bell(name) {
this.name = name;
}
bell.prototype.ribbonColor = "red";
bell.prototype.toString = function () {
return "I am a bell and my name is " + this.name + ".";
}
// Create individual bells
var bell01 = new bell("Bell 01");
var bell02 = new bell("Bell 02");
Qn 1: Implement lightUp method for all bells
// Add method to bell prototype which all bells will inherit
bell.prototype.lightUp = function () {
console.log(this.name + " has lighted up!");
}
Qn 2: Fix easy misuse of current constructor
// Use namespace to organize application code
var ChristmasBell = function (name) {
this.name = name;
}
// Create individual bells
var bell01 = new ChristmasBell("Bell 01");
var bell02 = new ChristmasBell("Bell 02");
Qn 3: Implement lightUp method for all bells
// Define a custom constructor method that sets one or more properties of a new object
var ChristmasBell = function (name, ribbonColor) {
this.name = name;
this.ribbonColor = ribbonColor || "red";
}
// Create individual bells
var bell01 = new ChristmasBell("Bell 01", "green");
var bell02 = new ChristmasBell("Bell 02");
Homework: What if I added the following line? Will the colors of the 2 bells change? Why?
ChristmasBell.prototype.ribbonColor = "yellow";