Created
November 15, 2011 17:27
-
-
Save DmitrySoshnikov/1367694 to your computer and use it in GitHub Desktop.
R-Proto-Class-Current-Class.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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