Skip to content

Instantly share code, notes, and snippets.

@andrewplummer
Created November 22, 2012 03:21
Show Gist options
  • Select an option

  • Save andrewplummer/4129295 to your computer and use it in GitHub Desktop.

Select an option

Save andrewplummer/4129295 to your computer and use it in GitHub Desktop.
Dead simple class inheritance
(function() {
var defineProperty = Object.defineProperty || function(obj, name, desc) {
obj[name] = desc.value;
};
var getOwnPropertyNames = Object.getOwnPropertyNames || function(obj) {
var names = [];
for(var key in obj) {
if(!obj.hasOwnProperty(key)) continue;
names.push(key);
}
return names;
};
var defineMethod = function(obj, name, method, enumerable) {
defineProperty(obj, name, {
value: method,
writable: true,
configurable: true,
enumerable: !!enumerable
});
};
var mixin = function(source) {
extend.call(this, source);
extend.call(this.prototype, source.prototype);
};
var extend = function(obj, enumerable) {
var names = getOwnPropertyNames(obj), i = names.length, key;
while(i--) {
key = names[i];
if(key && !(key in this)) {
defineMethod(this, key, obj[key], enumerable !== false);
}
}
};
// "inherits" can be called in both the construtor of the inheriting class:
//
// var Foo = Class(function Foo() {
// this.inherits(new Bar());
// });
//
// ... or outside it:
//
// var Foo = Class(function Foo() {});
// Foo.inherits(Bar);
//
// The idea behind this is that often the constructor of the parent class needs
// to be called, and calling it outside the context of the child class' constructor
// often makes no sense. So, the first method makes sense when the parent's constructor
// needs to be called, and the second makes sense when Foo simply inherits Bar's methods.
// This is effectively identical to a mixin, and in fact this is not true prototypal
// inheritance as the properties are being mixed in as non-enumerable methods instead of
// actually setting the prototype object itself. This could be done through __proto__,
// but it's dirtier and IE could not be supported.
var inherits = function(parent) {
var target = typeof this === 'function' ? this.prototype : this;
if(typeof parent === 'function') {
extend.call(target, parent.prototype, false);
} else {
extend.call(target, parent, false);
extend.call(target, parent.constructor.prototype, false);
}
};
Class = function(constructor) {
// Don't want to define methods on Function.prototype (yet),
// so define them directly for now.
defineMethod(constructor, 'mixin', mixin, true);
defineMethod(constructor, 'extend', extend, true);
defineMethod(constructor, 'inherits', inherits);
defineMethod(constructor.prototype, 'extend', extend);
defineMethod(constructor.prototype, 'inherits', inherits);
return constructor;
};
})();
@andrewplummer
Copy link
Author

Usage:

var Car = Class(function Car () {
   this._super();
});

Car.extend({});  ... // class methods
Car.prototype.extend({}); // instance methods
Car.inherits(Vehicle); // Very simple inheritance (actually a mixin)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment