Skip to content

Instantly share code, notes, and snippets.

@billmei
Created March 30, 2015 18:30
Show Gist options
  • Save billmei/a83f5002262e2e898a93 to your computer and use it in GitHub Desktop.
Save billmei/a83f5002262e2e898a93 to your computer and use it in GitHub Desktop.
Lesson plan for teaching JavaScript prototypes
// Floobits:
// https://floobits.com/Kortaggio/prototypes
// Inheritance Diagram:
// https://docs.google.com/drawings/d/1PTgRq2UPD0LilvZOFIpTWUsgzGo1iN7XdL7X6BXvA-U/edit?usp=sharing
// Hi guys! Today I'm going to tell you about prototypes in JavaScript.
// Before I get started, I want to ask you a question:
// How many of you have:
// - started a business?
// - you're taking this course because you want to start a business?
// Let's open a new business: a lemonade stand!
function Lemonade () {
}
///////////////////////
// REVIEW OF OBJECTS //
///////////////////////
// This is a constructor.
function Lemonade (brand) {
this.price = 2;
this.ingredients = {
"lemons" : 5,
"tbsp of sugar" : 16, // 1 cup
"cups of water" : 8
};
// Sidenote: If this was done in person in front of a real class,
// I would actually bring in a jug of store-bought lemonade for the class
this.servings = 3;
this.isCold = true;
this.brand = brand;
}
// 2 minutes
// Now, if you want to serve someone a glass of lemonade:
var delsCoolLemonade = new Lemonade("Del's Cool Lemonade");
console.log(delsCoolLemonade);
/* {
ingredients: { lemons: 5, 'tbsp of sugar': 16, 'cups of water': 8 },
servings: 3,
price: 2,
brand: 'Del\'s Cool Lemonade',
isCold: true
} */
//////////////////////////////////////////
// EXPLAIN WHY PROTOTYPES ARE IMPORTANT //
//////////////////////////////////////////
// For the people in this room that
// are thinking about starting their own business, I'll show you how prototypes
// can save you a lot of work when setting up your lemonade stand
// Your business takes off, and your customers want more drinks!
// Lets start serving orange juice and apple juice too:
function OrangeJuice () {
this.price = 1;
this.ingredients = {
"large oranges" : 6
};
this.servings = 3;
this.isCold = true;
}
var delsOJ = new OrangeJuice();
function AppleJuice () {
this.price = 1;
this.ingredients = {
"large apples" : 4,
"tbsp of sugar" : 6,
"cups of water" : 6
};
this.servings = 3;
this.isCold = true;
}
var delsAppleJuice = new AppleJuice();
// This is not efficient, we're repeating ourselves
// There are many shared properties between the three drinks.
// They're all juices! Lemonade is really just like "lemon juice"
// Let's create a Juice class
function Juice () {
this.servings = 3;
this.isCold = true;
}
/////////////////////////
// EXPLAIN INHERITANCE //
/////////////////////////
// We need to make OJ, AJ, and Lemonade have the same properties from our
// Juice object.
// PROTOTYPES
// "What type of thing is this?"
// The answer is, OJ, AJ, Lemonade, this is a "type of juice"
// In JavaScript world, this is known as "prototype"
Lemonade.prototype = new Juice();
OrangeJuice.prototype = new Juice();
AppleJuice.prototype = new Juice();
// delsAppleJuice still returns the same object
console.log(delsAppleJuice.isCold);
////////////////////////////
// PAUSE BEFORE CONTINUING
// Does all of this make sense so far? Any questions or anything I should clarify?
// 5 minutes
// Lets make Spiked Lemonade.
// This is exactly the same as lemonade except
// that it's alcoholic, and instead of $2, we're going to charge $4.
function SpikedLemonade () {
this.price = 4;
this.ingredients = {
"lemons" : 5,
"tbsp of sugar" : 16,
"cups of water" : 8,
"oz of vodka" : 2
};
// Alternate way of writing the ingredients
this.ingredients["oz of vodka"] = 2;
}
/////////////////////////////
// CHECK FOR UNDERSTANDING //
/////////////////////////////
// What should I do after writing the constructor
// to make sure that the SpikedLemonade inherits all its properties from Lemonade?
SpikedLemonade.prototype = new Lemonade("Del's Hard Lemonade");
var delsHardLemonade = new SpikedLemonade();
/////////////////////
// PROTOTYPE CHAIN //
/////////////////////
/*
Diagram:
https://docs.google.com/drawings/d/1PTgRq2UPD0LilvZOFIpTWUsgzGo1iN7XdL7X6BXvA-U/edit?usp=sharing
*/
// The default is "Object"
// if you don't specify a prototype.
// If you try to refer to a property that doesn't exist in the current object,
// JavaScript will go up the prototype chain to try to find that property
// Example:
console.log(delsHardLemonade.isCold);
// 8 minutes
// ATTACHING FUNCTIONS TO THE PROTOTYPE
// You're making enough lemonade now that you have to buy a lot of lemons.
// You have to make a shopping list to keep track
delsCoolLemonade.makeShoppingList = function (numPeople) {
var shoppingList = [];
for (var foodItem in this.ingredients) {
shoppingList.push(numPeople * (this.ingredients[foodItem] / this.servings) +
" " + foodItem);
}
return shoppingList;
};
// 9 minutes
console.log(delsCoolLemonade.makeShoppingList(12));
// If you run this, you get the output:
// [ '20 lemons', '64 tbsp of sugar', '32 cups of water' ]
// You want to do market research
// "Awesome Lemonade" is a better name than "Cool Lemonade".
// You run an A/B test of the two names
var delsCoolLemonade = new Lemonade("Del's Cool Lemonade");
var delsAwesomeLemonade = new Lemonade("Del's Awesome Lemonade");
// Now, you also have to build a shopping list for Awesome Lemonade
// But, you want makeShoppingList to exist for ALL lemonades, not just Cool Lemonade.
Lemonade.prototype.makeShoppingList = function () { /* ... */ };
// PAUSE TO EXPLAIN
// "constructor" is like the "blueprint" for the Lemonade object
// "prototype" is like the "blueprint" for the object
// When you say Lemonade.prototype = new Juice();, you're saying:
// "Make the initial blueprint for a Lemonade looks like exactly like Juice"
// You can change this blueprint later by putting stuff in the constructor,
// or by putting sub-properties into the prototype directly.
Lemonade.prototype.isSweet = true;
// 11 minutes
////////////////////////
// SUMMARY AND REVIEW //
////////////////////////
// The "prototype" is a special property of an object that refers to
// "What type of thing is this?"
// Every object has a prototype, and the default prototype is Object
// If you refer to it directly, you are referring to
// the blueprint of your object.
// Anything you attach to the prototype of an object will be attached to all instances
// of that object that you create. (Cool Lemonade vs Awesome Lemonade)
// The next time you want to start a new business, keep prototypes
// in the back of your mind.
// Example usage: to keep track of things like your employees, or customer data,
// or the addresses of your suppliers
/////////////////////////////
// CHECK FOR UNDERSTANDING //
/////////////////////////////
// Remember our A/B test between Cool Lemonade and Awesome Lemonade?
// I also want to calculate revenue for Awesome Lemonade
delsCoolLemonade.calculateCoolRevenue = function (numSold) {
return delsCoolLemonade.price * numSold;
};
delsAwesomeLemonade.calculateAwesomeRevenue = function (numSold) {
return delsAwesomeLemonade.price * numSold;
};
// How can I refactor this?
// Good answer: attach it to the Lemonade prototype
// Better answer: attach it to the Juice prototype (remember the prototype chain!)
Lemonade.prototype.calculateRevenue = function (numSold) {
return this.price * numSold;
};
/////////
// END //
/////////
// Any questions?
// Sidenote:
// Another advantage of prototypes is that it's faster,
// because you're not instantiating every method all the time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment