Skip to content

Instantly share code, notes, and snippets.

@draeton
Created December 22, 2011 05:10
Show Gist options
  • Save draeton/1508995 to your computer and use it in GitHub Desktop.
Save draeton/1508995 to your computer and use it in GitHub Desktop.
Playing with classes and inheritance
/*
* This has essentially turned into Resig's Simple JavaScript Inheritance
* with some minor modifications for class names and use strict,
* and getters ans setters
* http://ejohn.org/blog/simple-javascript-inheritance/
* http://ejohn.org/blog/javascript-getters-and-setters/
*/
(function (window) {
"use strict";
// function test
var _fnTest = /xyz/.test(function(xyz){}) ? /\b_super\b/ : /.*/;
// no operation
var _noop = function () {};
// super methods
var _makeSuper = function (name, method, proto) {
return function () {
var tmp = this._super;
this._super = proto[name] || _noop;
var ret = method.apply(this, arguments);
this._super = tmp;
return ret;
};
};
// the Base constructor for all classes
var Base = window.Base = function Base () {};
Base.extend = function (name, settings) {
var props = settings || {};
// prototypical inheritance
Base._extending = true;
var proto = new this();
Base._extending = false;
// add properties to prototype
var i, g, s;
for (i in props) {
if (props.hasOwnProperty(i)) {
if (typeof props[i] === "function" && _fnTest.test(props[i])) {
proto[i] = _makeSuper(i, props[i], this.prototype);
} else {
g = props.__lookupGetter__(i);
s = props.__lookupSetter__(i);
if (g || s) {
if (g) proto.__defineGetter__(i, g);
if (s) proto.__defineSetter__(i, s);
} else {
proto[i] = props[i];
}
}
}
}
// constructor
var Class = function Class () {
if (!Base._extending && this.initialize) {
this.initialize.apply(this, arguments);
}
};
// add extensibility
Class.extend = Base.extend;
// return constructor
Class.prototype = proto;
Class.prototype._class = name;
Class.prototype.constructor = Class;
return Class;
};
})(this);
(function (window) {
"use strict";
var Base = window.Base;
var Person = Base.extend("Person", {
initialize: function (name) {
this.name = name;
this.points = 100;
this.alive = true;
},
speak: function (text) {
console.log(text + " I am a " + this._class + "!");
},
damage: function (points) {
this.points += points;
if (this.points <= 0) {
this.die();
}
},
die: function () {
this.alive = false;
this.points = 0;
console.log(this.name + ", " + this + ", is dead.");
},
toPrimitive: function () {
return this._class;
},
toString: function () {
return this.toPrimitive();
},
valueOf: function () {
return this.toPrimitive();
}
});
var Ninja = Person.extend("Ninja", {
initialize: function (name) {
this._super(name);
this.points += 20;
},
chop: function (person) {
person.damage(-25);
}
});
var Samurai = Ninja.extend("Samurai", {
initialize: function (name) {
this._super(name);
this.points += 50;
},
slice: function (person) {
person.damage(-50);
}
});
var matthew = new Samurai("Matthew");
var michael = new Ninja("Michael");
console.log(matthew, michael);
})(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment