Suppose I want to include some calls to console.log
for some legitimate production reason, say for something like a unit test harness. Obviously I would not want this to throw a premature exception if the browser doesn't have a console
, or if no console is present.
What's the best way to create a simple log
function to log stuff to the console, or silently fail without error if no console is present?
The accepted answer to the question linked above:
var log = Function.prototype.bind.call(console.log, console); log.apply(console, ["this", "is", "a", "test"]);
Can this log
function be called normally on IE, and the use of apply
here is just to show it's possible? And, I assume from the linked question that this will fail if IE's console is closed when it runs, so log
won't work even after the console opens, correct? If that's wrong, can someone explain how it works?
This ycombinator article seems relevant. Are they are talking about the same IE behavior as the question linked above?
Function.prototype.apply.apply(console.log, [console, arguments]);
Works both on IE9 broken console.log, and regular console.log from other vendors. Same hack as using Array.prototype.slice to convert arguments into a real array.
This works nicely in my chrome console.
function echo(){
Function.prototype.apply.apply(console.log, [console, arguments]);
}
Simplified:
function echo(){
Function.apply.call(console.log, console, arguments);
}
Add a check and return:
function echo(){
return window.console && console.log &&
Function.apply.call(console.log, console, arguments);
}
The example above looks adequate to me. I don't have IE on hand to test it, though. Is this a reasonable approach for safely wrapping console.log
?
More questions
Following the link in nav's answer below, we see the code:
Function.prototype.call.call(console.log, console,
Array.prototype.slice.call(arguments));
What is the purpose of converting arguments
to an array in this case? I guess it must fail in some browser if you don't do this? And, opera weird behavior and console-less browsers aside, shouldn't something like this pretty much work for every other browser as well? And does prototype
serve a purpose in the above examples, or are we just being pedantic... Function.call.call
or Object.call.call
or for that matter isNaN.call.call
seem to work just as well as Function.prototype.call.call
.
Try using the code snippet below... (this is my preferred approach because it makes you independent of window.console)
So you may now try these in your code and see the result
Use Consolation
My ridiculously overengineered console:
console.log
statements in your codeconsole.error
,console.group
, and all such other methodsIt's amazing.
But really, you just shouldn't leave
console
statements lying around in your code.Behold and tremble! Presenting: Consolation.js
Sorry, there was a bug in my post. Don't know how I missed it.
The PROPER way to create a global console object, if it does not exist:
My solution is a little different. I create a standard shortcut for all console.log calls: In my case kag(whatever I want to report in the console).
I test for IE, if IE I send the results to an alert box. If Chrome then displays in the console. This also means IE will always work even in console is closed:
Code:
Yes, and yes. That particular example was aimed squarely at the "is it a real function" part of the linked question.
Correct. As explained in my answer on that question, the
console
object is not exposed until the first time the developer tools are opened for a particular tab. Most developers use a console shim, in which case theFunction#bind
approach becomes a little obsolete because you may as well use theFunction#apply.apply
method.There isn't one, it's redundant. Unless it's a custom log implementation, in which case the developer may have a reason to convert an arguments object to an array.
Well, yes and no. Some developer may have unwittingly changed
Function.call
to a custom function or value. Of course, they could breakFunction.prototype.call
too, but this is far less likely to happen by accident.I like to use:
It works in all browsers and is easy to understand.