Created
July 10, 2011 06:43
-
-
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.
This file contains 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
/* | |
* 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