A prototype is a property functions have. This property points points to an object.
Last active
August 16, 2019 20:04
-
-
Save rcanepa/1a310ac0314dbb04e407f6f6caa2605c to your computer and use it in GitHub Desktop.
JavaScript's prototype based inheritance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
No prototype inheritance is being used here. All cats, created with the factory | |
function, have a copy of the `sayName` function. What could go wrong if we had to | |
created thousands or millions of cats? | |
We can avoid having copies of the `sayName` function by using inheritance. | |
*/ | |
function catFactory(name, birthday) { | |
const cat = {} | |
cat.name = name | |
cat.birthday = birthday | |
cat.sayName = function () { | |
return cat.name | |
} | |
return cat | |
} | |
const walter = catFactory('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = catFactory('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
We use Object.create() to set the `catMethods` object as the prototype of | |
any cat created with the `catFactory` function. | |
From MDN web docs: | |
The Object.create() method creates a new object, using an existing object as | |
the prototype of the newly created object. | |
*/ | |
function catFactory(name, birthday) { | |
// Make the prototype of a cat the `catMethods` object. | |
const cat = Object.create(catMethods) | |
cat.name = name | |
cat.birthday = birthday | |
return cat | |
} | |
const catMethods = { | |
sayName: function () { | |
return this.name | |
} | |
} | |
const walter = catFactory('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = catFactory('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Instead of using the `catMethods` object as the prototype, we add the `sayName` method | |
to the `catFactory` function prototype. Then, we pass that prototype as argument in the | |
Object.create() call. The result is the same. | |
*/ | |
function catFactory(name, birthday) { | |
const cat = Object.create(catFactory.prototype) | |
cat.name = name | |
cat.birthday = birthday | |
return cat | |
} | |
catFactory.prototype.sayName = function () { | |
return this.name | |
} | |
const walter = catFactory('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = catFactory('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
We use the `new` keyword to create cat instances. This makes using Object.create() | |
unnecessary because it automatically set the `Cat` function prototype to each object | |
created by that function. We don't need to explicitely create an object and return it, | |
the `new` keyword approach does that for us. | |
*/ | |
function Cat(name, birthday) { | |
this.name = name | |
this.birthday = birthday | |
} | |
Cat.prototype.sayName = function () { | |
return this.name | |
} | |
const walter = new Cat('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = new Cat('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
ES6 includes the `class` keyword (which is syntactic sugar on top of what we saw | |
in the previous example). It makes the whole process simple. | |
*/ | |
class Cat { | |
constructor (name, birthday) { | |
this.name = name | |
this.birthday = birthday | |
} | |
sayName () { | |
return this.name | |
} | |
} | |
const walter = new Cat('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = new Cat('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Animal(name) { | |
this.name = name | |
} | |
Animal.prototype.sayName = function () { | |
return this.name | |
} | |
function Cat(name, birthday) { | |
// Call the Animal constructor | |
Animal.call(this, name) | |
this.birthday = birthday | |
} | |
Cat.prototype = Object.create(Animal.prototype) | |
Cat.prototype.constructor = Cat | |
// This is not the same as | |
// Cat.prototype = Animal.prototype | |
// This would make both classes use the same prototype objedt | |
Cat.prototype.eat = function () { | |
console.log(this.name, 'is eating now') | |
} | |
const walter = new Cat('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = new Cat('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' | |
gus.eat() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Animal(name) { | |
this.name = name | |
} | |
Animal.prototype.sayName = function () { | |
return this.name | |
} | |
function Cat(name, birthday) { | |
// Call the Animal constructor | |
Animal.call(this, name) | |
this.birthday = birthday | |
} | |
Cat.prototype = Object.create(Animal.prototype) | |
Cat.prototype.constructor = Cat | |
// This is not the same as | |
// Cat.prototype = Animal.prototype | |
// This would make both classes use the same prototype objedt | |
Cat.prototype.eat = function () { | |
console.log(this.name, 'is eating now') | |
} | |
const walter = new Cat('Walter', '01/23/86') | |
console.log(walter.name) | |
// => 'Walter' | |
console.log(walter.birthday) | |
// => '01/23/86' | |
console.log(walter.sayName()) | |
// => 'Walter' | |
const gus = new Cat('Gus', '02/11/91') | |
console.log(gus.name) | |
// => 'Gus' | |
console.log(gus.birthday) | |
// => '02/11/91' | |
console.log(gus.sayName()) | |
// => 'Gus' | |
gus.eat() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment