Skip to content

Instantly share code, notes, and snippets.

@DmitrySoshnikov
Created November 15, 2011 17:27
Show Gist options
  • Save DmitrySoshnikov/1367694 to your computer and use it in GitHub Desktop.
Save DmitrySoshnikov/1367694 to your computer and use it in GitHub Desktop.
R-Proto-Class-Current-Class.js
// https://mail.mozilla.org/pipermail/es-discuss/2011-November/018440.html
// see original lib here:
// https://gist.github.com/1366953
// https://gist.github.com/1330574
var Class = {
/**
*allocate
* Creates an instance. Default is
* the implementation of native `new'
*/
allocate: function () {
return Object.create(this);
},
/**
* new
* A wrapper over allocated and initialize
*/
new: function () {
var instance = this.allocate();
this.initialize.apply(instance, arguments);
return instance;
},
/**
* initialize
* Configure a newly created instance
*/
initialize: function () {},
/**
* super
*/
super: function (method) {
var parentName = '__' + method + '_invoke__';
var parentObject = this[parentName];
var proto;
if (parentObject) {
// deeper levels
proto = Object.getPrototypeOf(parentObject.proto);
} else {
// first level (proto of an instance) -- get the next level
proto = Object.getPrototypeOf(Object.getPrototypeOf(this));
}
this[parentName] = {proto: proto, level: (parentObject ? parentObject.level++ : 0)};
this.__superCall__ = {proto: proto, method: method};
var result = proto[method].apply(this, [].slice.call(arguments, 1));
delete this.__superCall__;
this[parentName].level--;
if (!this[parentName].level)
delete this[parentName];
return result;
}
};
/**
* class
* Just a wrapper over Object.create
*/
function class(methods) {
var parent = methods.extends || Class;
delete methods.extends;
var aClass = Object.create(parent);
for (var k in methods) {
let method = k;
let originalMethod = methods[method];
let newMethod = originalMethod;
if (typeof originalMethod == 'function') {
newMethod = function () {
if (this.__superCall__ && this.__superCall__.method != method) {
var oldSuperCall = this.__superCall__;
delete this.__superCall__;
var superResult = oldSuperCall.proto[method].apply(this, arguments);
this.__superCall__ = oldSuperCall;
return superResult;
}
return originalMethod.apply(this, arguments);
};
}
Object.defineProperty(aClass, k, {value: newMethod});
}
return aClass;
}
var One = class({
one: function () {
return this.two();
},
two: function () {
return "you win";
}
});
var Two = class({
extends: One,
one: function () {
return this.super("one");
},
two: function () {
return "broken";
}
});
var instance = Two.new();
console.log(instance.one());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment