Last active
April 1, 2017 23:20
-
-
Save thomd/119e893001bdd85367b556bd14932d0c to your computer and use it in GitHub Desktop.
Pitfalls on Prototypal Inheritance with JavaScript
This file contains hidden or 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
// | |
// Circle.prototype = Object.create(Shape.prototype) | |
// Circle.prototype.constructor = Circle | |
// | |
// shape constructor (parent) | |
var Shape = function(x = 0, y = 0) { | |
this.x = x | |
this.y = y | |
} | |
Shape.prototype = { | |
move: function(x, y) { | |
this.x += x | |
this.y += y | |
}, | |
position: function() { | |
return [this.x, this.y] | |
} | |
} | |
// circle constructor (child) | |
var Circle = function(r) { | |
Shape.call(this) | |
this.r = r | |
} | |
// set for Circle.prototype an object which has a __proto__ to Shape.prototype in order to inherit only it's methods | |
Circle.prototype = Object.create(Shape.prototype) | |
Circle.prototype.area = function() { | |
return Math.PI * this.r * this.r | |
} | |
Circle.prototype.constructor = Circle | |
// rectangle constructor (child) | |
var Rectangle = function(w, h) { | |
Shape.call(this) | |
this.w = w | |
this.h = h | |
} | |
// set for Rectangle.prototype an object which has a __proto__ to Shape.prototype in order to inherit only it's methods | |
Rectangle.prototype = Object.create(Shape.prototype) | |
Rectangle.prototype.area = function() { | |
return this.w * this.h | |
} | |
Rectangle.prototype.constructor = Rectangle | |
// now some instances: | |
var circle = new Circle(2) | |
circle.move(2, 2) | |
console.log(circle.constructor.name) // Circle | |
console.log(circle.position()) // [2, 2] | |
console.log(circle.area()) // 12,566... | |
var rectangle = new Rectangle(2, 3) | |
rectangle.move(2, 2) | |
console.log(rectangle.constructor.name) // Circle | |
console.log(rectangle.position()) // [2, 2] | |
console.log(rectangle.area()) // 6 |
This file contains hidden or 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
// | |
// Circle.prototype = Shape.prototype | |
// Circle.prototype.constructor = Circle | |
// | |
// shape constructor (parent) | |
var Shape = function(x = 0, y = 0) { | |
this.x = x | |
this.y = y | |
} | |
Shape.prototype = { | |
move: function(x, y) { | |
this.x += x | |
this.y += y | |
}, | |
position: function() { | |
return [this.x, this.y] | |
} | |
} | |
// circle constructor (child) | |
var Circle = function(r) { | |
Shape.call(this) | |
this.r = r | |
} | |
// reference Circle.prototype to Shape.prototype, so Circle will have Shape's methods, but when creating new methods for | |
// Circle, they will be created in fact at Shape - not Circle. This can yield to issues when sub-classing further | |
// objects from Shape | |
Circle.prototype = Shape.prototype | |
Circle.prototype.area = function() { | |
return Math.PI * this.r * this.r | |
} | |
Circle.prototype.constructor = Circle | |
// rectangle constructor (child) | |
var Rectangle = function(w, h) { | |
Shape.call(this) | |
this.w = w | |
this.h = h | |
} | |
// reference Rectangle.prototype to Shape.prototype, so Circle will have Shape's methods, but when creating new methods for | |
// Circle, they will be created in fact at Shape - not Circle. This can yield to issues when sub-classing further | |
// objects from Shape | |
Rectangle.prototype = Shape.prototype | |
// This will now overwrite the 'area' method from Circle, as this method is in fact set at Shape | |
Rectangle.prototype.area = function() { | |
return this.w * this.h | |
} | |
Rectangle.prototype.constructor = Rectangle | |
// now some instances: | |
var circle = new Circle(2) | |
circle.move(2, 2) | |
console.log(circle.constructor.name) // Circle | |
console.log(circle.position()) // [2, 2] | |
console.log(circle.area()) // NaN <- area method was overwritten by second sub-classing | |
var rectangle = new Rectangle(2, 3) | |
rectangle.move(2, 2) | |
console.log(rectangle.constructor.name) // Circle | |
console.log(rectangle.position()) // [2, 2] | |
console.log(rectangle.area()) // 6 |
This file contains hidden or 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
// | |
// Circle.prototype = new Shape() | |
// Circle.prototype.constructor = Circle | |
// | |
// shape constructor (parent) | |
var Shape = function() { | |
this.abstract = true | |
} | |
Shape.prototype = { | |
isAbstract: function() { | |
return this.abstract ? true : false | |
} | |
} | |
// circle constructor (child) | |
var Circle = function(r) { | |
this.r = r | |
} | |
// set for Circle.prototype an instance of Shape. Here you will also inherit the property 'abstract' of 'Shape' which | |
// should not and will yield a wrong result when calling 'circle.isAbstract' | |
Circle.prototype = new Shape() | |
Circle.prototype.area = function() { | |
return Math.PI * this.r * this.r | |
} | |
Circle.prototype.constructor = Circle | |
// rectangle constructor (child) | |
var Rectangle = function(w, h) { | |
Shape.call(this) | |
this.w = w | |
this.h = h | |
} | |
Rectangle.prototype = new Shape() | |
Rectangle.prototype.area = function() { | |
return this.w * this.h | |
} | |
Rectangle.prototype.constructor = Rectangle | |
// now some instances: | |
var circle = new Circle(2) | |
circle.move(2, 2) | |
console.log(circle.constructor.name) // Circle | |
console.log(circle.area()) // 12,566... | |
console.log(circle.isAbstract()) // true <- should be 'false' | |
var rectangle = new Rectangle(2, 3) | |
rectangle.move(2, 2) | |
console.log(rectangle.constructor.name) // Circle | |
console.log(rectangle.area()) // 6 | |
console.log(rectangle.isAbstract()) // true <- should be 'false' |
This file contains hidden or 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
// | |
// Circle.prototype = Object.create(Shape.prototype) | |
// | |
// shape constructor (parent) | |
var Shape = function() {} | |
Shape.prototype = {} | |
// circle constructor (child) | |
var Circle = function(r) { | |
this.r = r | |
} | |
Circle.prototype = Object.create(Shape.prototype) | |
Circle.prototype.area = function() { | |
return Math.PI * this.r * this.r | |
} | |
// now an instance: | |
var circle = new Circle(2) | |
console.log(circle.constructor.name) // Object <- should be 'Circle' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment