Last active
December 20, 2015 19:48
-
-
Save reynaldot/6185394 to your computer and use it in GitHub Desktop.
Followup notes on javascript inheritance after reading some of Stoyan Stefanov's Javascript Patterns book.
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
var assert = require('assert'); | |
/** | |
* Default pattern | |
* | |
* Inherits properties added to this and prototype | |
*/ | |
// parent constructor: | |
function Parent(name) { | |
this.name = name || 'foo'; | |
} | |
Parent.prototype.say = function() { | |
return this.name; | |
}; | |
// empty child constructor: | |
function Child(name) {} | |
function inherit(C, P) { | |
C.prototype = new P(); | |
} | |
inherit(Child, Parent); | |
var kid = new Child(); | |
assert.equal(kid.say(), 'foo'); | |
kid.name = 'bar'; | |
assert.equal(kid.say(), 'bar'); | |
delete kid.name; | |
assert.equal(kid.say(), 'foo'); |
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
var assert = require('assert'); | |
/** | |
* Rent-a-constructor pattern | |
* | |
* Inherits properties added to this inside the parent constructor | |
* Does not inherit members added to the prototype. | |
*/ | |
// parent constructor: | |
function Parent(name) { | |
this.name = name || 'foo'; | |
} | |
Parent.prototype.say = function() { | |
return this.name; | |
}; | |
// empty child constructor: | |
function Child() { | |
Parent.call(this); | |
} | |
var kid = new Child(); | |
assert(kid.hasOwnProperty('name')); | |
assert.equal(kid.prototype, undefined); | |
kid.name = 'bar'; | |
assert.equal(kid.name, 'bar'); | |
delete kid.name; | |
assert.equal(kid.name, undefined); |
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
var assert = require('assert'); | |
/** | |
* Rent and set Prototype | |
* | |
* Copies the parent's own members and references to the parent's reusable functionality. | |
*/ | |
// parent constructor: | |
function Parent(name) { | |
this.name = name || 'foo'; | |
} | |
Parent.prototype.say = function() { | |
return this.name; | |
}; | |
// empty child constructor: | |
function Child(name) { | |
Parent.apply(this, arguments); | |
} | |
Child.prototype = new Parent(); | |
var kid = new Child(); | |
assert.equal(kid.say(), 'foo'); | |
kid.name = 'bar'; | |
assert.equal(kid.say(), 'bar'); | |
delete kid.name; | |
assert.equal(kid.say(), 'foo'); |
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
var assert = require('assert'); | |
/** | |
* Share the Prototype | |
* | |
* All objects, including the parent, reference the same prototype. | |
* If a child modifies any of its prototype members, it will also modify its parent's. | |
* | |
* Children don't inherit the parent's properties. | |
*/ | |
// parent constructor: | |
function Parent(name) { | |
this.name = name || 'foo'; | |
} | |
Parent.prototype.say = function() { | |
return this.name; | |
}; | |
// empty child constructor: | |
function Child(name) {} | |
function inherit(C, P) { | |
C.prototype = P.prototype; | |
} | |
inherit(Child, Parent); | |
var kid = new Child(); | |
// Note how the prototype of an object is never made accessible. | |
assert.equal(kid.prototype, undefined); | |
// Also note the kid's own name property was not inherited. | |
assert.equal(kid.say(), undefined); | |
kid.name = 'bar'; | |
assert.equal(kid.say(), 'bar'); | |
// Now we proceed to screw up the parent's prototype method by modifying the children's | |
Child.prototype.say = function () { | |
return 'hello ' + this.name; | |
}; | |
var father = new Parent(); | |
assert.equal(father.say(), 'hello foo'); |
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
var assert = require('assert'); | |
/** | |
* A Temporary Constuctor | |
* | |
* The parent's prototype members are inherited by the child using a proxy object. | |
* This patterns breaks the direct link between parent's and child's prototype. | |
*/ | |
// parent constructor: | |
function Parent(name) { | |
this.name = name || 'foo'; | |
} | |
Parent.prototype.say = function() { | |
return this.name; | |
}; | |
// empty child constructor: | |
function Child(name) {} | |
function inherit(C, P) { | |
var F = function () {}; | |
F.prototype = P.prototype; | |
C.prototype = new F(); | |
} | |
var kid = new Child(); | |
// No chance we can now screw the parent's prototype method: | |
Child.prototype.say = function () { | |
return 'hello ' + this.name; | |
}; | |
var parent = new Parent(); | |
assert.equal(parent.say(), 'foo'); |
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
var assert = require('assert'); | |
/* | |
* Prototypal Inheritance - ECMAScript 5 | |
*/ | |
var parent = { | |
name: 'foo' | |
}; | |
var kid = Object.create(parent); | |
assert.equal(kid.name, 'foo'); | |
function Parent () { | |
this.name = 'foo'; | |
} | |
Parent.prototype.say = function () { | |
return this.name; | |
}; | |
// Inherit everything: | |
kid = Object.create(new Parent()); | |
assert.equal(kid.say(), 'foo'); | |
// Inherit only prototype members | |
kid = Object.create(Parent.prototype); | |
assert.equal(kid.say(), undefined); | |
// Inherit everything and override parent's property | |
kid = Object.create(new Parent(), {name: {value: 'bar'}}); | |
assert.equal(kid.say(), 'bar'); |
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
var assert = require('assert'); | |
/* | |
* Prototypal Inheritance | |
* | |
* No classes involved. Objects inherit from other objects. | |
*/ | |
// Parent created with literal object | |
var parent = { | |
name: 'foo' | |
}; | |
var object = function (o) { | |
var F = function () {}; | |
F.prototype = o; | |
return new F(); | |
}; | |
var kid = object(parent); | |
assert.equal(kid.name, 'foo'); | |
function Parent() { | |
this.name = 'foo'; | |
} | |
// Parent created with a constructor function instead. | |
Parent.prototype.say = function () { | |
return this.name; | |
}; | |
parent = new Parent(); | |
kid = object(parent); | |
assert.equal(kid.say(), 'foo'); | |
// Notice we could also inherit only the prototype methods | |
kid = object(Parent.prototype); | |
assert.equal(kid.say(), undefined); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment