257

According to this post it was in the beta, but it's not in the release?

Doug Harris
  • 3,169
  • 5
  • 29
  • 31
leeand00
  • 25,510
  • 39
  • 140
  • 297
  • 65
    `console.log` **is** there in IE8, but the `console` object isn't created until you open DevTools. Therefore, a call to `console.log` may result in an error, for example if it occurs on page load before you have a chance to open the dev tools. The [winning answer here](http://stackoverflow.com/questions/7742781/ie9-bug-javascript-only-works-after-opening-developer-tools-once-very-stran/) explains it in more detail. – SDC Jan 28 '13 at 15:31

17 Answers17

259

console.log is only available after you have opened the Developer Tools (F12 to toggle it open and closed). Funny thing is that after you've opened it, you can close it, then still post to it via console.log calls, and those will be seen when you reopen it. I'm thinking that is a bug of sorts, and may be fixed, but we shall see.

I'll probably just use something like this:

function trace(s) {
  if ('console' in self && 'log' in console) console.log(s)
  // the line below you might want to comment out, so it dies silent
  // but nice for seeing when the console is available or not.
  else alert(s)
}

and even simpler:

function trace(s) {
  try { console.log(s) } catch (e) { alert(s) }
}
Mister Lucky
  • 4,053
  • 2
  • 20
  • 18
  • No problem, yep it's quite typical. Those fun quirks we must learn to adjust and overcome! – Mister Lucky Mar 27 '09 at 15:54
  • 11
    Either way you shouldn't be calling console.log blindly because $other-browsers mightn't have it and thus die with a JavaScript error. +1 – Kent Fredric Mar 27 '09 at 17:05
  • 8
    you'll probably want to turn off traces before release anyhow though ;) – Kent Fredric Mar 27 '09 at 17:06
  • 2
    It makes sense not to log without developer tools being open, but making it throw an exception if rather than failing silently is the real confusing decision here. – ehdv Aug 03 '10 at 20:50
  • I want to create shims for console.log, etc - similar to how firebug lite used to do. Unfortunately, I can't get this to work in IE8 (since when I test for typeof console == 'undefined' - it always seems to return true). – mckoss Sep 13 '10 at 19:58
  • Doesn't Firebug's log statements behave the same way? They're not available until you open Firebug. – Frank Schwieterman Sep 29 '10 at 18:49
  • 4
    I want to point out a downside to wrapping console.log like this... you won't see anymore where your logging is coming from. I find that very useful sometimes on top of which is just looks wrong to have every console line originating from the exact same location in your code. – Martin Westin Aug 31 '11 at 11:36
  • @MisterLucky, why did you remove your alternative of creating a fake `console`? Was there something wrong with it? – Supr Jun 27 '12 at 12:28
  • 1
    @Supr, IE9 did overwrite it, and allowed any further calls to go to the real console methods, however IE8 would not overwrite it when you did open developer tools. – Mister Lucky Jul 18 '12 at 18:05
  • 2
    `alert` is evil. Some code behaves differently when alerts are used because the document loses focus, making bugs even harder to diagnose or creating ones where there weren't before. Also, if you accidentally leave a `console.log` in your production code, it is benign (assuming it doesn't blow up) - just silently logs to the console. If you accidentally leave an `alert` in your production code, the user experience is ruined. – Daniel Schilling Apr 02 '14 at 13:21
  • Dont forget the semi colons... ;-) function trace(s) { try { console.log(s);} catch (e) { alert(s);} } – shane lee Apr 24 '14 at 00:45
230

Even better for fallback is this:


   var alertFallback = true;
   if (typeof console === "undefined" || typeof console.log === "undefined") {
     console = {};
     if (alertFallback) {
         console.log = function(msg) {
              alert(msg);
         };
     } else {
         console.log = function() {};
     }
   }

jpswain
  • 14,642
  • 8
  • 58
  • 63
  • 71
    This is so impractical - how could you possibly debug a website with something that throws an alert for every call to console.log(). What if you have 10+ calls to log() in your code. What if msg is an object? [Walter's answer](http://stackoverflow.com/a/14246240/799588) makes much more sense, as a starting point. – Precastic Jun 22 '13 at 10:47
  • 7
    @Precastic: People will just stop using the browser :P – Amogh Talpallikar Mar 30 '14 at 04:44
  • See [my comment](http://stackoverflow.com/questions/690251/what-happened-to-console-log-in-ie8/690300#comment34790251_690300) on Mister Lucky's answer. – Daniel Schilling Apr 02 '14 at 13:22
  • 1
    an unobtrusive (though imperfect) alternative fallback is to set document.title. At least it doesn't lock up the browser with a modal alert. – brennanyoung Oct 01 '15 at 12:27
58

This is my take on the various answers. I wanted to actually see the logged messages, even if I did not have the IE console open when they were fired, so I push them into a console.messages array that I create. I also added a function console.dump() to facilitate viewing the whole log. console.clear() will empty the message queue.

This solutions also "handles" the other Console methods (which I believe all originate from the Firebug Console API)

Finally, this solution is in the form of an IIFE, so it does not pollute the global scope. The fallback function argument is defined at the bottom of the code.

I just drop it in my master JS file which is included on every page, and forget about it.

(function (fallback) {    

    fallback = fallback || function () { };

    // function to trap most of the console functions from the FireBug Console API. 
    var trap = function () {
        // create an Array from the arguments Object           
        var args = Array.prototype.slice.call(arguments);
        // console.raw captures the raw args, without converting toString
        console.raw.push(args);
        var message = args.join(' ');
        console.messages.push(message);
        fallback(message);
    };

    // redefine console
    if (typeof console === 'undefined') {
        console = {
            messages: [],
            raw: [],
            dump: function() { return console.messages.join('\n'); },
            log: trap,
            debug: trap,
            info: trap,
            warn: trap,
            error: trap,
            assert: trap,
            clear: function() { 
                  console.messages.length = 0; 
                  console.raw.length = 0 ;
            },
            dir: trap,
            dirxml: trap,
            trace: trap,
            group: trap,
            groupCollapsed: trap,
            groupEnd: trap,
            time: trap,
            timeEnd: trap,
            timeStamp: trap,
            profile: trap,
            profileEnd: trap,
            count: trap,
            exception: trap,
            table: trap
        };
    }

})(null); // to define a fallback function, replace null with the name of the function (ex: alert)

Some extra info

The line var args = Array.prototype.slice.call(arguments); creates an Array from the arguments Object. This is required because arguments is not really an Array.

trap() is a default handler for any of the API functions. I pass the arguments to message so that you get a log of the arguments that were passed to any API call (not just console.log).

Edit

I added an extra array console.raw that captures the arguments exactly as passed to trap(). I realized that args.join(' ') was converting objects to the string "[object Object]" which may sometimes be undesirable. Thanks bfontaine for the suggestion.

Community
  • 1
  • 1
Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75
  • 4
    +1 This is the only solution that starts to make sense. In what world would you **not** want to see the messages you are explicitly sending to the console! – Precastic Jun 22 '13 at 10:40
  • Great answer. Really liked the IIFE article you've mentioned, probably one of the best i've read so far. Could you please elaborate what is the purpose for these two lines in `trap` function: `var args = Array.prototype.slice.call(arguments); var message = args.join(' ');` ? Why do you pass the the arguments through this to the message? – user1555863 Aug 20 '13 at 13:19
  • 1
    @user1555863 I've updated my answer to answer your questions, see the section below the code. – Walter Stabosz Aug 20 '13 at 13:46
  • 1
    I think your "console.clear()" function's second line should read "console.raw.length = 0", instead of "console.row.length = 0". – Steve J Mar 16 '14 at 13:26
52

It's worth noting that console.log in IE8 isn't a true Javascript function. It doesn't support the apply or call methods.

James Wheare
  • 4,650
  • 2
  • 26
  • 22
44

Assuming you don't care about a fallback to alert, here's an even more concise way to workaround Internet Explorer's shortcomings:

var console=console||{"log":function(){}};
Leif Wickland
  • 3,693
  • 26
  • 43
  • +1 Since I'm scoping my code out in an anonymous function, placing console into a variable like this is the best solution to me. Helps me to not interfere with any other console hooking going on in other libraries. – Codesleuth Aug 13 '12 at 09:43
  • 2
    You want to start logging as soon as the developer tools have been opened. If you put this solution in a long-lived scope (e.g. registers inner functions as callbacks), it'll keep using the silent fallback. – Beni Cherniavsky-Paskin Sep 11 '13 at 04:35
  • +1/-1 = 0: +1 because the solution should be more based around preventing console.logs from breaking a site in IE - not used to debug... If you want to debug, just hit f12 and open the console :) -1 because you should be checking if console exists before overwriting it. – 1nfiniti Oct 10 '13 at 18:55
  • Some IE plugins define console and console.log, but as empty objects, not functions. – Lilith River Oct 15 '13 at 18:39
24

I really like the approach posted by "orange80". It's elegant because you can set it once and forget it.

The other approaches require you to do something different (call something other than plain console.log() every time), which is just asking for trouble… I know that I'd eventually forget.

I've taken it a step further, by wrapping the code in a utility function that you can call once at the beginning of your javascript, anywhere as long as it's before any logging. (I'm installing this in my company's event data router product. It will help simplify the cross-browser design of its new admin interface.)

/**
 * Call once at beginning to ensure your app can safely call console.log() and
 * console.dir(), even on browsers that don't support it.  You may not get useful
 * logging on those browers, but at least you won't generate errors.
 * 
 * @param  alertFallback - if 'true', all logs become alerts, if necessary. 
 *   (not usually suitable for production)
 */
function fixConsole(alertFallback)
{    
    if (typeof console === "undefined")
    {
        console = {}; // define it if it doesn't exist already
    }
    if (typeof console.log === "undefined") 
    {
        if (alertFallback) { console.log = function(msg) { alert(msg); }; } 
        else { console.log = function() {}; }
    }
    if (typeof console.dir === "undefined") 
    {
        if (alertFallback) 
        { 
            // THIS COULD BE IMPROVED… maybe list all the object properties?
            console.dir = function(obj) { alert("DIR: "+obj); }; 
        }
        else { console.dir = function() {}; }
    }
}
Benoit Garret
  • 14,027
  • 4
  • 59
  • 64
Chris Janicki
  • 521
  • 6
  • 6
  • 1
    Glad you like it :-) I use it for the exact reason you mention--b/c it's a good safety. It is just way too easy to put some "console.log" statements in your code for development and the forget to remove them later. At least if you do this, and put it at the top of every file where you use console.log, you will never have the site breaking in customers' browsers b/c they fail on console.log. Saved me before! Nice improvements, btw :-) – jpswain Dec 08 '11 at 07:03
  • 1
    "It is just way too easy to ... forget to remove them". One helpful thing I always do with temporary debug logging is prefix the code with an empty comment, `/**/console.log("...");` so it's easy to search and locate the temporary code. – Lawrence Dol Dec 05 '13 at 23:19
8

If you get "undefined" to all of your console.log calls, that probably means you still have an old firebuglite loaded (firebug.js). It will override all the valid functions of IE8's console.log even though they do exist. This is what happened to me anyway.

Check for other code overriding the console object.

user168290
  • 91
  • 1
  • 1
6

The best solution for any browser that lack a console is:

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());
GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
Vinícius Moraes
  • 3,506
  • 2
  • 22
  • 24
  • 1
    This has the glaring problem that objects or strings logged using console.group or console.GroupCollapsed will completely disappear. This is unnecessary, they should be mapped to console.log, if it's available. – Ben Aug 19 '13 at 23:18
4

There are so many Answers. My solution for this was:

globalNamespace.globalArray = new Array();
if (typeof console === "undefined" || typeof console.log === "undefined") {
    console = {};
    console.log = function(message) {globalNamespace.globalArray.push(message)};   
}

In short, if console.log doesn't exists (or in this case, isn't opened) then store the log in a global namespace Array. This way, you're not pestered with millions of alerts and you can still view your logs with the developer console opened or closed.

Nishi
  • 10,634
  • 3
  • 27
  • 36
calcazar
  • 1,120
  • 1
  • 12
  • 22
3

Here is my "IE please don't crash"

typeof console=="undefined"&&(console={});typeof console.log=="undefined"&&(console.log=function(){});
BrunoLM
  • 97,872
  • 84
  • 296
  • 452
2

I found this on github:

// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function f() {
    log.history = log.history || [];
    log.history.push(arguments);
    if (this.console) {
        var args = arguments,
            newarr;
        args.callee = args.callee.caller;
        newarr = [].slice.call(args);
        if (typeof console.log === 'object') log.apply.call(console.log, console, newarr);
        else console.log.apply(console, newarr);
    }
};

// make it safe to use console.log always
(function(a) {
    function b() {}
    for (var c = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","), d; !! (d = c.pop());) {
        a[d] = a[d] || b;
    }
})(function() {
    try {
        console.log();
        return window.console;
    } catch(a) {
        return (window.console = {});
    }
} ());
Sam Jones
  • 4,443
  • 2
  • 40
  • 45
2

I'm using Walter's approach from above (see: https://stackoverflow.com/a/14246240/3076102)

I mix in a solution I found here https://stackoverflow.com/a/7967670 to properly show Objects.

This means the trap function becomes:

function trap(){
    if(debugging){
        // create an Array from the arguments Object           
        var args = Array.prototype.slice.call(arguments);
        // console.raw captures the raw args, without converting toString
        console.raw.push(args);
        var index;
        for (index = 0; index < args.length; ++index) {
            //fix for objects
            if(typeof args[index] === 'object'){ 
                args[index] = JSON.stringify(args[index],null,'\t').replace(/\n/g,'<br>').replace(/\t/g,'&nbsp;&nbsp;&nbsp;');
            }
        }
        var message = args.join(' ');
        console.messages.push(message);
        // instead of a fallback function we use the next few lines to output logs
        // at the bottom of the page with jQuery
        if($){
            if($('#_console_log').length == 0) $('body').append($('<div />').attr('id', '_console_log'));
            $('#_console_log').append(message).append($('<br />'));
        }
    }
} 

I hope this is helpful:-)

Community
  • 1
  • 1
2
if (window.console && 'function' === typeof window.console.log) {
    window.console.log(o);
}
1

I like this method (using jquery's doc ready)... it lets you use console even in ie... only catch is that you need to reload the page if you open ie's dev tools after the page loads...

it could be slicker by accounting for all the functions, but I only use log so this is what I do.

//one last double check against stray console.logs
$(document).ready(function (){
    try {
        console.log('testing for console in itcutils');
    } catch (e) {
        window.console = new (function (){ this.log = function (val) {
            //do nothing
        }})();
    }
});
1

Here is a version that will log to the console when the developer tools are open and not when they are closed.

(function(window) {

   var console = {};
   console.log = function() {
      if (window.console && (typeof window.console.log === 'function' || typeof window.console.log === 'object')) {
         window.console.log.apply(window, arguments);
      }
   }

   // Rest of your application here

})(window)
George Reith
  • 13,132
  • 18
  • 79
  • 148
  • Good that it is limited in scope, could support the case when IE8 DevTools are open in the middle of code execution, but it doesn't work in IE8, console.log is an object, so it has no `apply` method. – Nishi Jun 23 '16 at 11:24
1

Make your own console in html .... ;-) This can be imprved but you can start with :

if (typeof console == "undefined" || typeof console.log === "undefined") {
    var oDiv=document.createElement("div");
    var attr = document.createAttribute('id'); attr.value = 'html-console';
    oDiv.setAttributeNode(attr);


    var style= document.createAttribute('style');
    style.value = "overflow: auto; color: red; position: fixed; bottom:0; background-color: black; height: 200px; width: 100%; filter: alpha(opacity=80);";
    oDiv.setAttributeNode(style);

    var t = document.createElement("h3");
    var tcontent = document.createTextNode('console');
    t.appendChild(tcontent);
    oDiv.appendChild(t);

    document.body.appendChild(oDiv);
    var htmlConsole = document.getElementById('html-console');
    window.console = {
        log: function(message) {
            var p = document.createElement("p");
            var content = document.createTextNode(message.toString());
            p.appendChild(content);
            htmlConsole.appendChild(p);
        }
    };
}
0

It works in IE8. Open IE8's Developer Tools by hitting F12.

>>console.log('test')
LOG: test
Konstantin Tarkus
  • 37,618
  • 14
  • 135
  • 121