Skip to content

Instantly share code, notes, and snippets.

@ydaniv
Created July 10, 2011 06:43
Show Gist options
  • Save ydaniv/1074335 to your computer and use it in GitHub Desktop.
Save ydaniv/1074335 to your computer and use it in GitHub Desktop.
simple wrapper for the ES5 Object.create mechanism and a function that fetches overridden methods from the prototype chain.
/*
* Copyright (C) 2011 Yehonatan Daniv <[email protected]>
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* supr.js is a simple wrapper for the Object.create mechanism of ES5,
* to ease the creation of objects via the Create function.
* supr.js also provides the supr function that fetches overridden methods
* from the prototype chain.
*
* example:
*
* var A = {
* name: 'Sam',
* who : function () {
* return this.name;
* }
* };
* var B = Create(A, {
* name: 'Bob',
* who : function () {
* return supr(this, 'who')() + ' is son of ' + this._parent_.name;
* }
* });
* var C = Create(B, {
* name: 'Alice'
* });
* console.log(B.who); // Bob is son of Sam
* console.log(C.who); // Alice is son of Bob
*/
(function (global, undefined) {
/*
* Some caching, and optionally, sandboxing
*/
var Object = global.Object,
getPrototypeOf = Object.getPrototypeOf,
getOwnDesc = Object.getOwnPropertyDescriptor,
objCreate = Object.create;
/*
* Define a sugary property for getting the prototype quickly
* Notice it ain't enumerable
*/
Object.defineProperty(Object.prototype, '_parent_', {
get : function () {
return getPrototypeOf(this);
},
set : function (obj) {} // if not defined causes errors in some places
});
/*
* Simple recursion for retrieving a property's owner
*/
function getPropertyOwner(obj, prop) {
return obj.hasOwnProperty(prop) ? obj : getPropertyOwner(obj._parent_, prop);
}
/*
* Gets an overridden method from down the prototype chain
*/
function supr(object, key) {
// if you named your function and not in strict mode you can drop the key argument
var _key = key === undefined ? arguments.callee.caller.name : key,
proto = object._parent_,
prop = proto[_key];
// make sure we got the actual super method and not the same one that went up the chain
if ( ! object.hasOwnProperty(_key) ) // this won't happen if this method is defined in Object
// find the last object that defined this property
prop = getPropertyOwner(proto, _key)
// get the super definition of this property
._parent_[_key];
// if it's a function then bind it to the right context
return typeof prop === 'function' ? prop.bind(object) : prop;
}
/*
* Helper function for turning simple objects into property descriptors
*/
function _asDescriptor(obj) {
var e, p, r = {};
for ( p in obj )
if ( e = getOwnDesc(obj, p) )
r[p] = e;
return r;
}
/*
* A simple wrapper for Object.create
*/
function Create(proto, self, as_generator) {
var me = _asDescriptor(self),
base = proto || {};
return as_generator ? function () {
return objCreate(base, me);
} : objCreate(base, me);
}
global.Create = Create;
global.supr = supr;
}(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment