Common idiom to avoid IE throw: Error: 'console' is undefined - javascript

I've installed firebug and I wrote all these log statements.
I've tested my app in IE and of course I've got "undefined" error.
What's the common idiom to avoid this.
I don't really feel like commenting all the console.log statements in my file nor to mock them.
Well I'm not sure what to do.

i usually make a wrapper function like so:
function log(obj) {
if (window.console && console.log) console.log(obj);
}
or you could do something like this at the beginning of your script file/element:
if (!window.console) {
window.console = {
log: function(obj){ /* define own logging function here, or leave empty */ }
};
}

Paul Irish has a better wrapper for console.log().
http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
This allows multiple arguments, and provides a history (for debugging) in case no console is there or (eg Firebug Lite) the console is created later.

Related

Is there a way to identify which JS is overwriting window.console?

I'm trying to troubleshoot a page with lots of JS, including ads, and something is causing window.console to be replaced which suppresses the typical console logging output that I would want to see.
Is there a way to identify which JS is overwriting window.console? Maybe trigger a breakpoint only when typeof(window.console) is modified?
Great question! And I think I can help.
Use Object.defineProperty https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
to recreacte .log property.
Smth like this:
Object.defineProperty(console, "log", {
set: function () { throw 'Hoh!' }
});
console.log = 'abc';

Website with JS doesn't work in IE9 until the Developer Tools is activated

I'm developing a complex website that heavily leverages jQuery and a number of scripts. On load of the site, none of my scripting is working (though I can confirm that other scripts are functioning fine). I wouldn't be posting such a lame question here on SE except for one thing:
The instant I hit F12 to turn on developer tools so I can debug my issue, everything instantly works perfectly!
Worse, if I shut down the browser, start it up, turn on Dev Tools first and visit the site, everything works as expected.
So I can't even debug the darned problem because Dev Tools fixes it! What could Dev Tools be doing that makes things work? Does it change the UA (I do some jQuery.browser detection)? Does it do something to doctype?
EDIT
All my console logging is wrapped in the following wrapper utility function:
function log(msg){
if (console){
console.log(msg);
}
}
Any thoughts or suggestions I could try would be welcome. I'll post here if I find a solution.
I appreciate I'm pretty late to the party here, but I've got a solution for IE9 that's a little different.
(function() {
var temp_log = [];
function log() {
if (console && console.log) {
for (var i = 0; i < temp_log.length; i++) {
console.log.call(window, temp_log[i]);
}
console.log.call(window, arguments);
} else {
temp_log.push(arguments);
}
}
})();
Basically instead of console.log you use log. If console.log exists then it works as normal, otherwise it stores log entries in an array and outputs them on the next log where the console is available.
It would be nice if it pushed the data as soon as the console is available, but this is less expensive than setting up a custom setInterval listener.
Updated function (1 October 2012)
I've updated this script for my own use and thought I'd share it. It has a few worthy improvements:
use console.log() like normal, i.e. no longer need to use non-standard log()
supports multiple arguments, e.g. console.log('foo', 'bar')
you can also use console.error, console.warn and console.info (though outputs them as console.log)
script checks for native console every 1000ms and outputs the buffer when found
I think with these improvements, this has become a pretty solid shim for IE9. Check out the GitHub repo here.
if (!window.console) (function() {
var __console, Console;
Console = function() {
var check = setInterval(function() {
var f;
if (window.console && console.log && !console.__buffer) {
clearInterval(check);
f = (Function.prototype.bind) ? Function.prototype.bind.call(console.log, console) : console.log;
for (var i = 0; i < __console.__buffer.length; i++) f.apply(console, __console.__buffer[i]);
}
}, 1000);
function log() {
this.__buffer.push(arguments);
}
this.log = log;
this.error = log;
this.warn = log;
this.info = log;
this.__buffer = [];
};
__console = window.console = new Console();
})();
You have console calls, in IE these will fail if the dev tools are not open. A simple fix is to wrap any console calls in a function like:
function log(msg) {
if(console)
console.log(msg);
}
I have hacked it the following way
<script type="text/javascript">
(function () {
if (typeof console == "undefined") {
console = {
log : function () {}
}
}
})();
</script>
And this is the first script element in the .
Most of the other solutions should work great, but here's a short one liner if you don't care about catching log messages if the console is not available.
// Stub hack to prevent errors in IE
console = window.console || { log: function() {} };
This lets you still use the native console.log function directly still instead of wrapping it with anything or having a conditional each time.
I find it much more convenient to simply use console && console.log('foo', 'bar', 'baz') rather than use a wrapper function.
The code you provided:
function logError(msg){
if (console) {
console.log(msg);
} else {
throw new Error(msg);
}
}
Will produce an error for IE when dev tools are closed because console will be undefined.
The console.log wrapper that I used was not sufficient to detect the console in IE9. Here's the wrapper that works from a related question on SE:
function logError(msg){
try {
console.log(msg);
} catch (error) {
throw new Error(msg);
}
}
function log(msg){
try {
console.log(msg);
} catch (error) { }
}
A proper test for the availability of the console object would be:
if (typeof console === "undefined" || typeof console.log === "undefined")
If you have multiple parallel script files, maybe the files are being loaded/executed in a different order with developer tools on/off.
I have run into this issue many times. Basically with variables we do this to check if they are valid
var somevar;
if (somevar)
//do code
this works because somevar will resolve to undefined. But if your checking a window property for example. window.console.
if (console) <---- this throws an exception
You cannot do the same check. The browser treats it differently. Basically only doing this
if (window.console) <---- will NOT throw an exception if undefined
//some code
this will work the same as the first example. So you need to change your code to
function log(msg){
if (window.console){
console.log(msg);
}
}

javascript error and exception handler

is it possible to register an error or exception handler/function that will be executed when a javascript error or exception occurs? I just feel wrapping all codes in try/catch block seems very tedious and inefficient.
window.onerror = function (msg, file, line) {
// handle error here
}
Supported by:
Chrome 13+
Firefox 6.0+
Internet Explorer 5.5+
Opera 11.60+
Safari 5.1+
Andy E's answer (+1) tells you how to do it.
That said, JavaScript isn't really meant to have caught execeptions in the same sense that, say, Java does. If your code is throwing exceptions, pull up a console and use the debugger to fix them. JS exceptions are slow, and really not meant to be used for flow control. A method won't throw an exception unless there's a serious problem — and it's usually a programming error.
Here's an alternative answer than the window.onerror solution. This isn't something I've used in production, but is something that I just like because of the flexibility (i.e. you could use it to debug things like timing how long a method took or something).
Whilst you could probably pass window into it (don't quote me on that, and don't think it's a good idea) it does work if you have all your methods in an object:
(function(obj) {
for (var name in obj) {
if (typeof(obj[name]) == 'function') {
currentMethod = obj[name];
obj[name] = function() {
try {
currentMethod();
}
catch (e) {
alert('Exception Handler: ' + e);
}
};
}
}
}(myObject));
Here's it working: http://jsfiddle.net/jonathon/kpYnW/
Basically, it goes through each property in your object, finds the ones that are functions and wraps them in a try/catch (or whatever else you want).
Whether or not it's efficient is a different matter - I've just found it a very useful technique for debugging. Unfortunately I can't remember the original place I read it but if anyone knows, please add as a comment.

Helper code to write to firebug logs, that doesn't break if using IE/Chrome etc

Is there any helper code out there that will allow me to write to firebug's log window, but at the same time not break if using IE/chrome etc.
Put this at the top of your first JavaScript include:
if(console === undefined) var console = { log: function() { } };
A simple check for existence should work.
if ("console" in window)
console.log("Log message!");
PS Chrome and IE7/IE8 have a console :-)

Bad idea to leave "console.log()" calls in your production JavaScript code?

I have a bunch of console.log() calls in my JavaScript.
Should I comment them out before I deploy to production?
I'd like to just leave them there, so I don't have to go to the trouble of re-adding the comments later on if I need to do any more debugging. Is this a bad idea?
It will cause Javascript errors, terminating the execution of the block of Javascript containing the error.
You could, however, define a dummy function that's a no-op when Firebug is not active:
if(typeof console === "undefined") {
console = { log: function() { } };
}
If you use any methods other than log, you would need to stub out those as well.
As others have already pointed it, leaving it in will cause errors in some browsers, but those errors can be worked around by putting in some stubs.
However, I would not only comment them out, but outright remove those lines. It just seems sloppy to do otherwise. Perhaps I'm being pedantic, but I don't think that "production" code should include "debug" code at all, even in commented form. If you leave comments in at all, those comments should describe what the code is doing, or the reasoning behind it--not blocks of disabled code. (Although, most comments should be removed automatically by your minification process. You are minimizing, right?)
Also, in several years of working with JavaScript, I can't recall ever coming back to a function and saying "Gee, I wish I'd left those console.logs in place here!" In general, when I am "done" with working on a function, and later have to come back to it, I'm coming back to fix some other problem. Whatever that new problem is, if the console.logs from a previous round of work could have been helpful, then I'd have spotted the problem the first time. In other words, if I come back to something, I'm not likely to need exactly the same debug information as I needed on previous occasions.
Just my two cents... Good luck!
Update after 13 years
I've changed my mind, and now agree with the comments that have accumulated on this answer over the years.
Some log messages provide long-term value to an application, even a client-side JavaScript application, and should be left in.
Other log messages are low-value noise and should be removed, or else they will drown out the high-value messages.
If you have a deployment script, you can use it to strip out the calls to console.log (and minify the file).
While you're at it, you can throw your JS through JSLint and log the violations for inspection (or prevent the deployment).
This is a great example of why you want to automate your deployment. If your process allows you to publish a js file with console.logs in it, at some point you will do it.
To my knowledge there is no shorter method of stubbing out console.log than the following 45 characters:
window.console||(console={log:function(){}});
That's the first of 3 different versions depending on which console methods you want to stub out all of them are tiny and all have been tested in IE6+ and modern browsers.
The other two versions cover varying other console methods. One covers the four basics and the other covers all known console methods for firebug and webkit. Again, in the tiniest file sizes possible.
That project is on github: https://github.com/andyet/ConsoleDummy.js
If you can think of any way to minimize the code further, contributions are welcomed.
-- EDIT -- May 16, 2012
I've since improved on this code. It's still tiny but adds the ability to turn the console output on and off: https://github.com/HenrikJoreteg/andlog
It was featured on The Changelog Show
You should at least create a dummy console.log if the object doesn't exist so your code won't throw errors on users' machines without firebug installed.
Another possibility would be to trigger logging only in 'debug mode', ie if a certain flag is set:
if(_debug) console.log('foo');
_debug && console.log('foo');
Hope it helps someone--I wrote a wrapper for it a while back, its slightly more flexible than the accepted solution.
Obviously, if you use other methods such as console.info etc, you can replicate the effect. when done with your staging environment, simply change the default C.debug to false for production and you won't have to change any other code / take lines out etc. Very easy to come back to and debug later on.
var C = {
// console wrapper
debug: true, // global debug on|off
quietDismiss: false, // may want to just drop, or alert instead
log: function() {
if (!C.debug) return false;
if (typeof console == 'object' && typeof console.log != "undefined") {
console.log.apply(this, arguments);
}
else {
if (!C.quietDismiss) {
var result = "";
for (var i = 0, l = arguments.length; i < l; i++)
result += arguments[i] + " ("+typeof arguments[i]+") ";
alert(result);
}
}
}
}; // end console wrapper.
// example data and object
var foo = "foo", bar = document.getElementById("divImage");
C.log(foo, bar);
// to surpress alerts on IE w/o a console:
C.quietDismiss = true;
C.log("this won't show if no console");
// to disable console completely everywhere:
C.debug = false;
C.log("this won't show ever");
this seems to work for me...
if (!window.console) {
window.console = {
log: function () {},
group: function () {},
error: function () {},
warn: function () {},
groupEnd: function () {}
};
}
Figured I would share a different perspective. Leaving this type of output visible to the outside world in a PCI application makes you non-compliant.
I agree that the console stub is a good approach. I've tried various console plugins, code snippets, including some fairly complex ones. They all had some problem in at least one browser, so I ended up going with something simple like below, which is an amalgamation of other snippets I've seen and some suggestions from the YUI team. It appears to function in IE8+, Firefox, Chrome and Safari (for Windows).
// To disable logging when posting a production release, just change this to false.
var debugMode = false;
// Support logging to console in all browsers even if the console is disabled.
var log = function (msg) {
debugMode && window.console && console.log ? console.log(msg) : null;
};
Note: It supports disabling logging to the console via a flag. Perhaps you could automate this via build scripts too. Alternatively, you could expose UI or some other mechanism to flip this flag at run time. You can get much more sophisticated of course, with logging levels, ajax submission of logs based on log threshold (e.g. all Error level statements are transmitted to the server for storage there etc.).
Many of these threads/questions around logging seem to think of log statements as debug code and not code instrumentation. Hence the desire to remove the log statements. Instrumentation is extremely useful when an application is in the wild and it's no longer as easy to attach a debugger or information is fed to you from a user or via support. You should never log anything sensitive, regardless of where it's been logged to so privacy/security should not be compromised. Once you think of the logging as instrumentation it now becomes production code and should be written to the same standard.
With applications using ever more complex javascript I think instrumentation is critical.
As other have mentions it will thrown an error in most browsers. In Firefox 4 it won't throw an error, the message is logged in the web developer console (new in Firefox 4).
One workaround to such mistakes that I really liked was de&&bug:
var de = true;
var bug = function() { console.log.apply(this, arguments); }
// within code
de&&bug(someObject);
A nice one-liner:
(!console) ? console.log=function(){} : console.log('Logging is supported.');
Yes, it's bad idea to let them running always in production.
What you can do is you can use console.debug which will console ONLY when the debugger is opened.
https://developer.mozilla.org/en-US/docs/Web/API/console/debug

Categories

Resources