Skip to content

Instantly share code, notes, and snippets.

@influx6
Created September 12, 2012 20:57
Show Gist options
  • Save influx6/3709875 to your computer and use it in GitHub Desktop.
Save influx6/3709875 to your computer and use it in GitHub Desktop.
HasOwnProperty Shim
In my heavy search to both understand the underline code and functionality of most
of the libraries i am building and managing,the one pure function that seems to have always eluded me was the hasOwnProperty function attributed to all JS objects.
I know browser support is widespread and i thank God for that,but am not the
type to just use something i don't understand,after a long,
mind bending,play testing in the js console to both understand how the prototyping system
works,how and why new objects point directly to the prototype,i finally came up with a shim that works 90% of the time even far more better than that located in the Modernizr annotated source code,ya you heard me better.
It seems the trick was really on how prototypes and constructors are
assigned and also depends on you how deep you wish to go into that tree,since the 'in'(for in loop and others) handle going deep within the prototype
and object tree there is not need to try to recreate that,therefore this function searches only one level deep.Anyway to much talk,heres the shim:
//written by Alexander Adeniyi Ewetumo
hasOwn = function(obj,elem,value){
if(Object.hasOwnProperty){
//return Object.hasOwnProperty.call(obj,elem);
}
var keys,constroKeys,protoKeys,state = false,fn = function(e,i){
if(value){
state = (e === value) ? true : false;
return;
}
state = true;
};
if(!this.isFunction(obj)){
/* when dealing pure instance objects(already instantiated
* functions when the new keyword was used,all object literals
* we only will be checking the object itself since its points to
* its prototype against its constructors.prototype
* constroKeys = this.keys(obj.constructor);
*/
keys = this.keys(obj);
//ensures we are not dealing with same object re-referening,if
//so,switch to constructor.constructor call to get real parent
protoKeys = this.keys(
((obj === obj.constructor.prototype) ? obj.constructor.constructor.prototype : obj.constructor.prototype)
);
if(this.any(keys,elem,(value ? fn : null)) && !this.any(protoKeys,elem,(value ? fn : null)))
return state;
}
/* when dealing with functions we are only going to be checking the
* object itself vs the objects.constructor ,where the
* objects.constructor points to its parent if there was any
*/
//protoKeys = this.keys(obj.prototype);
keys = this.keys(obj);
constroKeys = this.keys(obj.constructor);
if(this.any(keys,elem,(value ? fn : null)) && !this.any(constroKeys,elem,(value ? fn : null)))
return state;
};
The any and keys function are custom functions created for my utility belt for my http://github.com/influx6/Stub library.
The trick was simple when dealing directly on checking the prototype,to get rather the obj.constructor.constructor.prototype of the prototype
to get to the parents prototype or else we endup just getting back the same prototype if its just obj.constructor.prototype,and on the pure function checked,
nothing more than check the object itself and its constructor(obj.constructor),
now the case of checking an object may be confusing at first seems
we checking the object as before in the function case,
the real kicker here is that when at a pure function level before it gets instantied with the 'new' keyword,the function points to its own constructor,
therefore Function.constructor points to its parent constructor which is
that of the Function object,
while in the case of prototype or instantiated objects,is that the instantiated function now points to its prototype,
therefore the need to use the constructor.constructor.prototype to get to its
parent real prototype.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment