public
Last active

Tiny Little JavaScript Classes

  • Download Gist
tlc.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
// 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;
};

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.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.