Created
February 26, 2015 22:39
-
-
Save saksmt/020e5f62e819a81f018e to your computer and use it in GitHub Desktop.
Extension for JavaScript providing object oriented feature
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
(function (global) { | |
'use strict'; | |
/** | |
* @return {Function} Abstract function placeholder | |
*/ | |
Function.prototype.makeAbstract = function () { | |
return function () { | |
throw new Error('Abstract method can\'t be called.'); | |
}; | |
}; | |
/** | |
* Factory method to create abstract methods. | |
* @returns {Function} | |
*/ | |
Function.abstractMethod = function () { | |
var method = function () {}; | |
return method.makeAbstract(); | |
}; | |
/** | |
* Check if protected-data was injected | |
* @returns {boolean} | |
*/ | |
Function.prototype.isProtectedInjected = function () { | |
return false; | |
}; | |
/** | |
* Inject protected-data object to class | |
* @private | |
* @param Class {Function} Class | |
* @param protectedData {Object} Protected-data object | |
* @return {Function} Result class | |
*/ | |
function injectProtected(Class, protectedData) { | |
return (function (Native) { | |
function Overridden() { | |
var args = Array.prototype.map.call(arguments, function (value) { return [value]; }); | |
args.unshift(protectedData); | |
args.unshift(null); | |
return (new (Function.prototype.bind.apply(Native, args))()); | |
} | |
Overridden.prototype = new Native({}); | |
Overridden.getNative = function () { | |
return Native; | |
}; | |
Overridden.isProtectedInjected = function () { | |
return true; | |
}; | |
return Overridden; | |
}(Class)); | |
} | |
/** | |
* Get native class without injection of protected | |
* @returns {Function} Class | |
*/ | |
Function.prototype.getNative = function () { | |
return this; | |
}; | |
/** | |
* Extend from @a ParentClass | |
* @param {Function} ParentClass | |
* @return {Function} Result class | |
*/ | |
Function.prototype.extend = function (ParentClass) { | |
var protectedData = {}, | |
parent, | |
me = this.getNative(); | |
if (ParentClass.isProtectedInjected()) { | |
ParentClass = injectProtected(ParentClass.getNative(), protectedData); | |
} | |
parent = new ParentClass(); | |
me.prototype = parent; | |
me.prototype.constructor = me; | |
protectedData.parent = parent; | |
if (me.isProtectedInjected()) { | |
me = injectProtected(me, protectedData); | |
} | |
me.prototype = parent; | |
me.prototype.constructor = me; | |
return me; | |
}; | |
/** | |
* Injects protected-data object to class | |
* @example | |
* function SomeClass(protectedData/\* , ... *\/) { | |
* protectedData.protectedMethod = function () {}; | |
* protectedData.protectedVariable = 'Access only from children and self'; | |
* /\* ...Realization... *\/ | |
* }.injectProtected() | |
* @returns {Function} | |
*/ | |
Function.prototype.injectProtected = function () { | |
return injectProtected(this, {}); | |
}; | |
global.objectOriendedExtension = true; | |
}(Function, global)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment