Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Created December 10, 2011 18:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gordonbrander/1455798 to your computer and use it in GitHub Desktop.
Save gordonbrander/1455798 to your computer and use it in GitHub Desktop.
Tiny Little JavaScript Classes
// Create a prototype bridge between two functions.
var __bridge = function(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
return child;
};
// Merge any number of objects together.
// The first object has it's reference modified
// (doesn't return a new object).
// The last object property wins.
//
// Serves the same purpose as jQuery.extend and _.extend.
var __merge = function (obj) {
var objects = Array.prototype.slice.call(arguments, 1),
key, i, objN;
for (i=0; i < objects.length; i++) {
objN = objects[i];
for (key in objN) {
// Don't copy built-in or inherited object properties.
if (!objN.hasOwnProperty(key)) continue;
obj[key] = objN[key];
}
}
return obj;
};
// Minimal classical inheritance via object literals.
// Inspired by jashkenas' Proposal: <https://gist.github.com/1329619>.
//
// Creates a constructor function -- all items in the object will get
// copied to the prototype. If the first argument is another
// constructor function, this class will create a prototype bridge.
//
// This approach only does prototype chaining and doesn't emulate
// super or static.
//
// Usage:
//
// var Bunny = __class({
// hop: function (length) { ... }
// });
//
// var JackRabbit = __class(Bunny, {
// constructor: function (type) {
// this.type = type;
// },
// skip: function (length) { ... }
// });
//
// var myJackRabbit = new Jackrabbit('grey');
// myJackRabbit.hop();
// myJackRabbit.skip();
var __class = function (a, b) {
var obj, parent, child;
// Handle the two different argument formulations
// Case 1: parent, object.
// Case 2: object, undefined
b ? (parent = a, obj = b) : obj = a;
// Create constructor using:
//
// * `constructor` property of object, if set
// * OR patch in parent constructor if a parent has been passed in
// * OR use an empty function if no parent is assigned.
child = (
obj.hasOwnProperty('constructor') ?
obj.constructor :
(
parent ?
function () {
parent.prototype.constructor.apply(this, arguments);
} :
function () {}
)
);
// Make a prototype bridge between child and parent.
parent && __bridge(child, parent);
// Assign properties in our object literal to the prototype of our
// new constructor. This will also override properties inherited
// from the parent prototype.
__merge(child.prototype, obj);
return child;
};
@gordonbrander
Copy link
Author

Another take on Classical inheritance in JS. The goals for this snippet are:

  • Small - you should save code weight with inheritance, not increase it.
  • Simple - breaks down JavaScript inheritance into easy-to-understand steps.
  • Useful - exposes the useful bits of machinery for other uses (__merge, __bridge).
  • Efficient - should use prototype chaining, not object copying.

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