Validating existence of object elements
I got tried of writing stuff like
if( app.user == undefined || app.user.address == undefined || app.user.address.zip == undefined){
...
}
So I made a little function to test existence of elements in objects. Originally, I bound it on Object.prototype but I found out the hard way that this is a problem (and later why it's a problem). Instead, it uses a trick from sugar.js to make the function non-enumerable so it doesn't break key-value loops. This means that you have to check if it has already been defined first, because you can't overwrite it once it has been set.
if(Object.prototype.hasProp === undefined){
Object.defineProperty(Object.prototype, 'hasProp', {
value: function() {
var args = Array.prototype.slice.call(arguments);
for( var i=args.length; i-->0; ){
if( typeof args[i] !== "string" ){
throw new TypeError(typeof args[i] + " given in place of string");
}
var period = args[i].indexOf('.');
if(period>-1){
if(!this[args[i].substr(0, period)].hasProp(args[i].substr(period+1))){
return false;
}else{
continue;
}
}
if(this[args[i]]==undefined){
return false;
}
}
return true;
},
enumerable: false
});
}
That means you can do this:
d={a: "bark", b: 0, c: undefined, d: [], e: { a: { b: '1' } }, f: ""};
d.hasProp('a', 'b'); # true
d.hasProp('c'); # false
d.hasProp('e.a'); # true
d.hasProp('e.b'); # false
d.hasProp('e.a.b'); # true
d.hasProp('e.a.c'); # false
d.hasProp('d', 'f'); # true
d.hasProp('a.b'); # false
Note that this is different from hasOwnProperty, since hasOwnProperty is unsafe (can be overwritten) and d.hasOwnProperty('c') === true since d.c exists even though it is undefined.
The original situation is now if( !app.hasProp('user.address.zip')) does the trick. Note: Doesn't work on IE<=8. Should be safe everywhere else.
Minified
void 0===Object.prototype.hasProp&&Object.defineProperty(Object.prototype,"hasProp",{value:function(){for(var a=Array.prototype.slice.call(arguments),b=a.length;0<b--;){if("string"!==typeof a[b])throw new TypeError(typeof a[b]+" given in place of string");var c=a[b].indexOf(".");if(-1<c)if(this[a[b].substr(0,c)].a(a[b].substr(c+1)))continue;else return!1;if(void 0==this[a[b]])return!1}return!0},enumerable:!1});