-
-
Save frankieshakes/408067 to your computer and use it in GitHub Desktop.
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
// wrap in a closure to get at the global, | |
// no matter where we are. | |
(function () { this.env = this.env || "prod" })() | |
// in production mode, be fast. | |
// in development/testing mode, add some error checking. | |
function Class (ctor, parent, proto) { | |
if (typeof parent === "object") { | |
proto = parent | |
parent = null | |
} | |
proto = proto || {} | |
if (env === "prod") { | |
// no type checking, no function.apply | |
return Extend(ctor, parent, proto) | |
} | |
// debug mode. Add the "new" check, and being slow is ok. | |
function c () { | |
if (!(this instanceof c)) { | |
throw new Error("Constructors must be called with 'new'") | |
} | |
ctor.apply(this, arguments) | |
} | |
return Extend(c, parent, proto) | |
} | |
function Extend (child, parent, proto) { | |
var existing = child.prototype | |
if (parent) { | |
child.prototype = Object.create(parent.prototype) | |
for (var p in proto) child.prototype[p] = proto[p] | |
} else child.prototype = proto | |
child.parent = parent.prototype | |
for (var i in existing) child.prototype[i] = existing[i] | |
parent.prototype.constructor = parent | |
child.prototype.constructor = child | |
return child | |
} | |
// need this | |
if (typeof Object.create !== "function") Object.create = function (p) { | |
function f () {} | |
f.prototype = p | |
return new f | |
} | |
// birth and death make the best OOP examples. | |
function Animal (species) { | |
this.species = species | |
this.alive = true | |
} | |
Class(Animal, | |
{ reproduce : function () { | |
var c = new this.constructor | |
c.species = this.species | |
return c | |
} | |
, kill : function () { | |
for (var i in this) { | |
// can't do things when you're dead | |
if (typeof this[i] === "function") this[i] = null | |
} | |
this.alive = false | |
} | |
}) | |
function Mammal (species) { | |
this.parent.constructor.call(this, species) | |
} | |
Class(Mammal, Animal, | |
{ reproduce : function (partner) { | |
if (!partner) return null | |
if (partner.species !== this.species) return null | |
if ( | |
(this.sex === "M" && partner.sex !== "F") | |
|| (this.sex === "F" && partner.sex !== "M") | |
|| (this.sex !== "M" && this.sex !== "F") | |
) { | |
return null | |
} | |
// wrong time of the month? | |
if (Math.floor(Math.random() * 100) < 40) return null | |
var c = this.parent.reproduce.call(this) | |
, sex = Math.floor(Math.random() * 101) | |
c.sex = (sex > 50) ? "M" | |
: (sex < 50) ? "F" | |
: "X" | |
c.mother = this.sex === "M" ? partner : this | |
c.father = this.sex === "M" ? this : partner | |
return c | |
} | |
}) | |
// alternative construction pattern, | |
// put the constructor right in the Class() call | |
var Human = Class | |
( function (name, sex, wealth) { | |
this.parent.constructor.call(this, "homo sapiens") | |
this.name = name | |
this.sex = sex ? String(sex).toUpperCase().charAt(0) : "X" | |
this.wealth = parseFloat(wealth) || 0 | |
this.children = [] | |
} | |
, Mammal | |
, { reproduce : function (partner, boyName, girlName) { | |
var c = this.parent.reproduce.call(this, partner) | |
c.name = c.sex === "F" ? girlName : boyName | |
this.adopt(c) | |
partner.adopt(c) | |
return c | |
} | |
, adopt : function (child) { | |
this.children.push(child) | |
// kids are expensive! | |
this.wealth /= 2 | |
partner.wealth /= 2 | |
} | |
, kill : function () { | |
this.parent.kill.call(this) | |
if (!this.children.length) return | |
var estate = this.wealth / this.children.length | |
this.children.forEach(function (child) { child.wealth += estate }) | |
} | |
, work : function (wage, howLong) { | |
var self = this | |
setTimeout(function () { self.wealth += howLong * wage }, howLong) | |
} | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment