Dr. Greg Bernstein
Updated April 25th, 2021
OOP = Object Oriented Programming
__prototype__
property and its chainingclass
declaration to create OOP classesextends
declaration for use in OOP inheritanceA Plain English Guide to JavaScript Prototypes. Clearest and most logical explanation I’ve seen.
Understanding “Prototypes” in JavaScript. Written in 2011 and covers ECMAScript 5.1. Well written and organized.
class
ReferencesTry all the examples as you read the following slides
It will really help things sink in
__proto__
propertyNote __proto__
is in the ES6 standard but it has been a de facto standard in many browsers for quite a while.
var myObjA = {stuff: "Think about stuff", number: 42};
var myObjB = {course: "CS3520", students: 34};
myObjB.__proto__ = myObjA;
console.log(myObjB); // Doesn't look different
console.log(myObjB.stuff); // How?
__proto__
var myObjA = {stuff: "Think about stuff", number: 42};
var myObjB = {course: "CS3520", students: 34};
var myObjC = {music: "Metal Baroque", guitarist: "JS Bach"};
myObjB.__proto__ = myObjA;
myObjC.__proto__ = myObjB;
console.log(myObjC); // Doesn't look different
console.log(myObjC.number); // How?
JavaScript looks for properties (including functions) on every object on the __proto__
chain until null
is encountered.
console.log(myObjC)
console.log(myObjC.__proto__)
console.log(myObjC.__proto__.__proto__)
console.log(myObjC.__proto__.__proto__.__proto__)
console.log(myObjC.__proto__.__proto__.__proto__.__proto__)
for (var prop in myObjC) {
console.log(`${prop} has value ${myObjC[prop]}`);
}
console.log("Keys for myObjC:");
console.log(Object.keys(myObjC));
From MDN
for...in
loops: traverses all enumerable properties and its prototype chain
Object.keys(o)
: returns an array with all the own enumerable properties’ names (“keys”) of an object o.
From MDN
Object.getOwnPropertyNames(o)
: returns an array containing all own properties’ names (enumerable or not) of an object o.From plain english
New / updated properties are assigned to the object, not to the prototype
Let’s add a property to myObjC
already in myObjB
or myObjA
myObjC.number = 3;
myObjC.course = "Web Dev";
console.log(myObjC)
console.log(myObjC.__proto__)
console.log(myObjC.__proto__.__proto__)
__proto__
prototype
and constructor
properties (not covered)The raw use of these mechanisms for inheritance hierarchies is somewhat error prone so ES6 introduced classes to help us out.
JavaScript classes do not add any new functionality, just much easier and more readable syntax to set up prototypical inheritance hierarchies and provide access to parent functions.
See MDN class
class Board {
constructor() { // all properties here
this.year = 2010;
this.make = "Mikes Lab";
this.weight = "10lbs";
this.style = "Formula";
}
about() { // nice simple method definition
return `${this.year} ${this.make} ${this.style} board`;
}
sailRecommendation() { // nice simple method definition
return `${this.style} sails`;
}
}
Much nicer syntax, same implementation
var b1 = new Board();
b1.about();
b1.sailRecommendation();
console.log(b1.__proto__)
console.log(b1.__proto__.constructor)
b1 instanceof Board
Classes can only contain method definitions, not data properties;
When defining methods, you use shorthand method definitions;
Unlike when creating object literals, you do not separate method definitions in class bodies with commas;
Start with a base class:
class Mammal {
constructor(commonName) {
this.backbone = true;
this.neocortex = true;
this.name = commonName;
}
locomotion() {
return "usually walking, but not always";
}
speak() {
return "Some kind of mammal sound";
}
}
Extend from a base class using extend
keyword:
class Marsupial extends Mammal {
constructor(commonName) {
super(commonName); // parent constructor
this.pouch = true;
this.aussie = "likely";
}
speak() {
return "Some kind of Marsupial sound";
}
}
mam1 = new Mammal("Kitty");
mam1.locomotion();
mam1.speak();
mars1 = new Marsupial("Taz Devil");
mars1.speak();
mars1.locomotion();
Object.keys(mars1)
Array [ "backbone", "neocortex", "name", "pouch", "aussie" ]
Object.keys(mam1)
Check if the prototype chain is setup:
console.log(mam1)
console.log(mam1.__proto__)
console.log(mam1.__proto__.constructor)
console.log(mars1)
console.log(mars1.__proto__)
console.log(mars1.__proto__.constructor)
console.log(mars1.__proto__.__proto__)
console.log(mars1.__proto__.__proto__.constructor)
mam1 instanceof Mammal
mars1 instanceof Mammal
mars1 instanceof Marsupial
mam1 instanceof Marsupial
Summarized from Deep Dive into Classes
Subclasses are declared with the class keyword, followed by an identifier, and then the extends keyword, followed by an identifier.
If your derived class needs to refer to the class it extends, it can do so with the super keyword.
Summarized from Deep Dive into Classes
this
.Summarized from Deep Dive into Classes
In JavaScript, there are precisely two use cases for the super keyword.
Within subclass constructor calls.
To refer to methods in the superclass. Within normal method definitions, derived classes can refer to methods on the parent class with dot notation: super.methodName
.