The conclusion was, to use typeof for any "global" variable and a direct conditional check against undefined within the scope of a function where you know the variables are at least declared. That makes sense, because if( some_undefined_variable !== undefined ) throws a reference error.
I played around with that in mind and I thought, this might be interesting for fellow Javascripters. My first testcase looked like this:
var loops = 1e6,
foo;
console.time('typeof');
while(loops--) {
if( typeof foo !== 'undefined' ) {}
}
console.timeEnd('typeof');
loops = 1e6;
console.time('direct');
while(loops--) {
if( foo !== undefined) {}
}
console.timeEnd('direct');
with the result of:
typeof: 421ms direct: 603ms
Pretty interesting. So here it looks like, typeof is faster than just comparing a variable against undefined. I couldn't really believe what I've seen here. I thought that is probably because I'm in the global context and my Javascript engine (SpiderMonkey) does some kind of wierd scope chain lookups for "undefined". Anyway, it should improve the overall performance to put that code into a function (-context), which I did:
(function() {
var loops = 1e6,
foo;
console.time('typeof');
while(loops--) {
if( typeof foo !== 'undefined' ) {}
}
console.timeEnd('typeof');
loops = 1e6;
console.time('direct');
while(loops--) {
if( foo !== undefined) {}
}
console.timeEnd('direct');
}());
Results:
typeof: 54ms direct: 185ms
As expected, this has a better overall performance, but still typeof is way faster than a plain conditional check vs. undefined. Well, the important thing I forgot here is to keep a local reference (some people call it: cache) for the undefined value:
(function(undef) {
var loops = 1e6,
foo;
console.time('typeof');
while(loops--) {
if( typeof foo !== 'undefined' ) {}
}
console.timeEnd('typeof');
loops = 1e6;
console.time('direct');
while(loops--) {
if( foo !== undef) {}
}
console.timeEnd('direct');
}());
Final results:
typeof: 51ms direct: 38ms
Yay! That's the way to go and that's why you always should try to cache objects / object propertys before accessing (if its not a problem to have a static reference).
My default Javascript opener when using jQuery looks like:
(function(win, doc, $, undef) {
// lots of beautiful code that can access win(window),
// doc(document), $(jQuery) and undef(undefined)
}(this, this.document, jQuery));
However, to be honest I'm still not 100% sure why this affects the undefined value that much. Cached references are faster to access (fact), totally makes sense for objects and propertys, but the undefined value is not a property as far as I know.
update:
I was wrong. undefined really is a property in the global object (window).
'undefined' in window; // = true
This explains why the cached version of the undefined value is way faster. Thanks to Stackoverflow member CMS who pointed me on this fact here.
sorry for the improper comment, but 1e6 is a pretty neat shortcut.
ReplyDeleteScript against right-click on a blog speaking on good programming... Defeat all author's credibility, don't you think ?
ReplyDeleteCtrl+C Ctrl+V
ReplyDelete