Last active
February 19, 2016 20:17
-
-
Save distransient/a3b039c9ae93bd05d524 to your computer and use it in GitHub Desktop.
Javascript prototype demonstration
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
// since we know how prototype works, now we can forget it exists | |
// and forfeit from using it in our code, because of the penalty | |
// it incurs in the form of extra complexity | |
function numberArray() { | |
var x = { value: Array.apply(null, arguments) } | |
x.sum = function () { return this.value.reduce(function(x, y) { return x + y }) } | |
return x | |
} | |
// We may not be able to index numberArray directly (we have | |
// to access numberArray.value), but its implementation and | |
// likelihood of breaking in non-obvious ways is much smaller. | |
console.log(numberArray(2, 3, 9, 1).sum()) // => 15 | |
// This will list the properties "value" and "sum", | |
// but we can do better, since we don't want methods | |
// on our data structure to be enumerable. | |
for(var x in numberArray(1, 8, 2)) | |
console.log(x) | |
function improvedNumberArray() { | |
// This creates the object with a non-configurable, | |
// enumerable, or writable field named "sum" with | |
// the value of the function. | |
var x = Object.create(null, { sum: { value: | |
function () { return this.value.reduce( | |
function(x, y) { return x + y }) } } }) | |
x.value = Array.apply(null, arguments) | |
return x | |
} | |
console.log(improvedNumberArray(2, 3, 9, 1).sum()) // => 15 | |
for(var x in improvedNumberArray(1, 8, 2)) | |
console.log(x) // => "value"; Sum isn't enumerated! |
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
// Prototype inheritance | |
function ArrayWithValue(firstValue) { | |
var x = Array.isArray(this) ? this : [] | |
// Apply inheritance of methods to value | |
// Note: changing the prototype of an object whether via | |
// __proto__ or Object.setPrototypeOf, is going to be slow. | |
// This is only unavoidable in the case of how weird Arrays | |
// are in JS. If you're working with a non-array superclass, | |
// use Object.create() instead. | |
// To learn more about the weirdness of ECMAScript Arrays, | |
// read this: http://goo.gl/Mw5Ows | |
if (!x instanceof ArrayWithValue) | |
Object.setPrototypeOf(x, ArrayWithValue.prototype) | |
x.push(firstValue) | |
return x | |
} | |
// Inherit methods from array | |
ArrayWithValue.prototype = new Array; | |
// => ['hello, world!'] | |
console.log(new ArrayWithValue('hello, world!')) | |
// Subclass implementation | |
function TwoValues(firstValue, secondValue) { | |
// TODO: experiment more with subclasses of Array subclasses | |
var x = ArrayWithValue.call(Object.setPrototypeOf( | |
[], TwoValues.prototype), firstValue) | |
x.push(secondValue) | |
return x | |
} | |
// This is why we use "new SuperClass" instead of "SuperClass" | |
// We can modify the prototype and add methods to the subclass | |
// through the prototype now, without mutating the superclass | |
TwoValues.prototype = new ArrayWithValue | |
TwoValues.prototype.sum = function () { | |
return this.reduce(function(x, y) { return x + y }) } | |
console.log((new TwoValues(3,4)).sum()) // => 7 |
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
// Prototype extension | |
// don't do this on globals! it's just for demonstration. | |
// modifying global prototypes will change how | |
// instances of that class behave for *everyone* | |
Object.prototype.add = function(x) { return this + x } | |
console.log('foo'.add('bar')) // => 'foobar' | |
console.log((1).add(1)) // => 2 |
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
// (simplified) Javascript implementation of "new" operator | |
// This isn't meant to be used, but is more of a tool to | |
// understand how "new" works. | |
function neu(x, args) { | |
// Makes an object using specified prototype | |
// I should eventually write a little implementation | |
// of this as well, for clarity on the prototype chain. | |
var instance = Object.create(x.prototype || null) | |
// Applies constructor to object, returns instance either | |
// returned from constructor, or modified by constructor. | |
return x.apply(instance, args) || instance | |
} | |
// To demonstrate... | |
function SimpleClass(width, height) { | |
this.width = width | |
this.height = height | |
} | |
SimpleClass.prototype.area = function () { | |
return this.width * this.height } | |
console.log((new SimpleClass(2,3)).area()) // => 6 | |
console.log((neu(SimpleClass, [2,3])).area()) // also => 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment