views:

295

answers:

1

I wanted to keep my logging statements as short as possible while preventing console from being accessed when it doesn't exist; I came up with the following solution:

var _ = {};
if (console) {
    _.log = console.debug;
} else {
    _.log = function() { }
}

To me, this seems quite elegant, and it works great in Firefox 3.6 (including preserving the line numbers that make console.debug more useful than console.log). But it doesn't work in Safari 4. [Update: Or in Chrome. So the issue seems to be a difference between Firebug and the Webkit console.] If I follow the above with

console.debug('A')
_.log('B');

the first statement works fine in both browsers, but the second generates a "TypeError: Type Error" in Safari. Is this just a difference between how Firebug and the Safari Web Developer Tools implement console? If so, it is VERY annoying on Apple's Webkit's part. Binding the console function to a prototype and then instantiating, rather than binding it directly to the object, doesn't help.

I could, of course, just call console.debug from an anonymous function assigned to _.log, but then I'd lose my line numbers. Any other ideas?

+4  A: 

First, if console is indeed undefined (as it is in browsers such as IE), you'll get an error. You should check it instead as a property of the global object, which is window in browsers. It's also a good idea in general to test a feature before using it, so I've added a test for the debug method.

Possibly the implementation of console.debug in Safari relies on its value of this being a reference to console, which will not be the case if you call it using _.log (this will instead be a reference to _). Having done a quick test, this does seem to be the case and the following fixes the problem:

var _ = {};
if (typeof window.console != "undefined"
       && typeof window.console.debug == "function") {
    _.log = function() {
        window.console.debug.apply(window.console, arguments);
    }
} else {
    _.log = function() { }
}
Tim Down
Right, that's the conventional approach, but it has a serious flaw: it loses the line numbers. If you call _.log() from anywhere in the app, the console will report that output as being generated from within the _.log() function, not the original source. So the benefit of using console.debug() instead of console.log() is lost.
Trevor Burnham
In that case, wouldn't it be easier just to stick to using `console` without any alias or wrapper, and just define it with stub methods if it doesn't exist? For example: `if (typeof window.console != "undefined") { window.console = { debug: function() {} } }` etc.
Tim Down
I think you're right, Tim (though you mean `typeof window.console == "undefined"` rather than `!=`, right?). I should perhaps abandon my quest for brevity in favor of just assigning a dummy console as needed.
Trevor Burnham
Oops. Yes, I did mean `==` rather than `!=`.
Tim Down