objects-mixing
Version:
This module is for mixing an objects in one super object.It uses __proto__ property to combine objects, but not just copying properties and methods.
96 lines (88 loc) • 4.49 kB
JavaScript
function isValSet(varToCheck)
{
return typeof(varToCheck) !== "undefined" && varToCheck !== null ;
}
function typeOfVar(varToCheck)
{
return {}.toString.call(varToCheck);
}
function checkArg(arg, numOfVals)
{
var retArr = [];
for(var argInd=0;argInd<arg.length;argInd++) {retArr[argInd] = arg[argInd];}
if ( typeOfVar(retArr) !== "[object Array]")
{
return new Error("Wrong type of the first argument");
}
if ( retArr.length < numOfVals )
{
return new Error("Wrong number of the functions into array");
}
return retArr;
}
function getConstr(constrDescr)
{
constructorPri = constrDescr[0];
return typeof constructorPri !== "function" ? new Error("One of the argument is not a function") : constructorPri;
}
function getArgs(constrDescr)
{
return ( ( typeOfVar(constrDescr[1]) !== "[object Array]" ) || ( constrDescr[1].length = 1 ) ) ? ( typeOfVar(constrDescr[1]) !== "[object Array]" ? ([constrDescr[1]]):(constrDescr[1]) ) : ( constrDescr[1] ) ;
}
function getThis(constrDescr)
{
return ( typeof(constrDescr[2]) === "object" && isValSet(constrDescr[2]) ? ( constrDescr[2] ) : ( undefined ) );
}
function splitObjectConstructors()
{
var objConstructors, firstConstrDescr, nextConstrDescr, constructorPri, argumentsPri, constructorSl, argumentsSl, valOfThis, valOfThisSl;
function retObjConstructor(constr, argumentsToConstr, valOfThis) {
return constr.apply( isValSet(valOfThis) ? valOfThis : this, argumentsToConstr);
}
//check arguments
if ( (objConstructors = checkArg(arguments,2)) instanceof Error ) throw objConstructors;
//if it is not function-constructor, but it is already object
objPri = ( typeof(objConstructors[0]) === "object" && typeOfVar(objConstructors[0]) !== "[object Array]" ) && ( isValSet(objConstructors[0]) ) ? objConstructors[0] : function(){
//create first object
//try to get first function-constructor and it's properties
if ( (firstConstrDescr = checkArg(objConstructors[0],1)) instanceof Error ) throw firstConstrDescr;
if ((constructorPri = getConstr(firstConstrDescr)) instanceof Error) throw constructorPri;
if ((argumentsPri = getArgs(firstConstrDescr)) instanceof Error) throw argumentsPri;
if (( valOfThis = getThis(firstConstrDescr)) instanceof Error) throw argumentsPri;
retObjConstructor.prototype = constructorPri.prototype;
return new retObjConstructor(constructorPri, argumentsPri, valOfThis);
}.call();
//for each object or function-constructor desription
objConstructors.forEach(
function(objConstructorDescr, index, array){
if ( index == 0 ) return;
//if it is not function-constructor, but it is already object
; objSl = ( typeof(objConstructorDescr) === "object" && typeOfVar(objConstructorDescr) !== "[object Array]" ) && ( isValSet(objConstructorDescr) ) ? objConstructorDescr : function() {
//create next object
//try to get next function-constructor and it's properties
if ( (nextConstrDescr = checkArg(objConstructorDescr,1)) instanceof Error ) throw(nextConstrDescr);
if ((constructorSl = getConstr(nextConstrDescr)) instanceof Error) throw (constructorSl);
if ((argumentsSl = getArgs(nextConstrDescr)) instanceof Error) throw argumentsSl;
if (( valOfThisSl = getThis(nextConstrDescr)) instanceof Error) throw argumentsPri;
retObjConstructor.prototype = constructorSl.prototype;
return new retObjConstructor(constructorSl, argumentsSl, valOfThisSl);
}.call();
//find prototype of the first object equal to Object
var objMixin = objPri;
while( true )
{
if ( objMixin.__proto__.hasOwnProperty("constructor") && objMixin.__proto__.constructor == Object ) {break;}
else { objMixin = objMixin.__proto__;};
}
//change prototype that is equal to Object instance into first object prototypes chain to the next object
objMixin.__proto__ = objSl;
}
);
return objPri;
}
function addMixinObject(obj)
{
splitObjectConstructors(this, obj);
}
Object.prototype.addMixin = addMixinObject;
module.exports = exports = splitObjectConstructors;