O que aconteceu com o console.log no IE8?

254

De acordo com este post , estava na versão beta, mas não está no lançamento?

leeand00
fonte
65
console.log é lá em IE8, mas o consoleobjeto não é criado até que você DevTools abertos. Portanto, uma chamada para console.logpode resultar em um erro, por exemplo, se ocorrer no carregamento da página antes que você tenha a chance de abrir as ferramentas de desenvolvimento. A resposta vencedora aqui explica mais detalhadamente.
SDC 28/01

Respostas:

229

Ainda melhor para o fallback é o seguinte:


   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
fonte
71
Isso é tão impraticável - como você pode depurar um site com algo que gera um alerta para cada chamada para console.log (). E se você tiver mais de 10 chamadas para log () no seu código. E se msg for um objeto? A resposta de Walter faz muito mais sentido, como ponto de partida.
Precastic
7
@Precastic: As pessoas vão parar de usar o navegador: P
Amogh Talpallikar
Veja meu comentário sobre a resposta do Sr. Lucky.
Daniel Schilling
1
uma alternativa alternativa discreta (embora imperfeita) é definir document.title. Pelo menos, não bloqueia o navegador com um alerta modal.
brennanyoung
257

O console.log estará disponível somente depois que você abrir as Ferramentas do desenvolvedor (F12 para alternar entre abrir e fechar). O engraçado é que, depois de abri-lo, você pode fechá-lo e ainda publicá-lo através das chamadas console.log, e elas serão vistas quando você o reabrir. Estou pensando que isso é um tipo de bug e pode ser corrigido, mas veremos.

Provavelmente vou usar algo assim:

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)
}

e ainda mais simples:

function trace(s) {
  try { console.log(s) } catch (e) { alert(s) }
}
Senhor Lucky
fonte
11
De qualquer forma, você não deve chamar o console.log às cegas, porque $ other-browsers podem não tê-lo e, portanto, morrem com um erro de JavaScript. +1
Kent Fredric
8
você provavelmente vai querer desligar traços antes do lançamento de qualquer maneira embora;)
Kent Fredric
2
Faz sentido não registrar sem que as ferramentas do desenvolvedor estejam abertas, mas fazer com que seja uma exceção se, em vez de falhar silenciosamente, é a verdadeira decisão confusa aqui.
ehdv
4
Quero apontar uma desvantagem em agrupar o console.log assim ... você não verá mais de onde vem o log. Acho que às vezes é muito útil, além do que parece errado, ter todas as linhas de console originárias do mesmo local exato no seu código.
Martin Westin
2
alerté mau. Alguns códigos se comportam de maneira diferente quando os alertas são usados ​​porque o documento perde o foco, tornando os bugs ainda mais difíceis de diagnosticar ou criando aqueles que não existiam antes. Além disso, se você acidentalmente deixar um console.logno seu código de produção, é benigno (supondo que ele não exploda) - apenas registra silenciosamente no console. Se você acidentalmente deixar um alertno seu código de produção, a experiência do usuário será arruinada.
Daniel Schilling
56

Esta é a minha opinião sobre as várias respostas. Eu realmente queria ver as mensagens registradas, mesmo que não tivesse o console do IE aberto quando elas foram acionadas, então as empurro para uma console.messagesmatriz criada por mim. Também adicionei uma função console.dump()para facilitar a visualização de todo o log. console.clear()esvaziará a fila de mensagens.

Essas soluções também "manipulam" os outros métodos do console (que eu acredito que todos se originam da API do Firebug Console )

Finalmente, essa solução está na forma de um IIFE , portanto, não polui o escopo global. O argumento da função de fallback é definido na parte inferior do código.

Eu apenas o solto no meu arquivo JS principal, que está incluído em todas as páginas, e esqueço.

(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)

Algumas informações extras

A linha var args = Array.prototype.slice.call(arguments);cria uma matriz do argumentsobjeto. Isso é necessário porque os argumentos não são realmente uma matriz .

trap()é um manipulador padrão para qualquer uma das funções da API. Eu passo os argumentos para messageque você obtenha um log dos argumentos que foram passados ​​para qualquer chamada de API (não apenas console.log).

Editar

Eu adicionei uma matriz extra console.rawque captura os argumentos exatamente como passados trap(). Eu percebi que args.join(' ')estava convertendo objetos para a string "[object Object]"que às vezes pode ser indesejável. Obrigado bfontaine pela sugestão .

Walter Stabosz
fonte
4
+1 Esta é a única solução que começa a fazer sentido. Em que mundo você não gostaria de ver as mensagens que está enviando explicitamente para o console!
Precastic
Ótima resposta. Gostei muito do artigo do IIFE que você mencionou, provavelmente um dos melhores que já li até agora. Você poderia elaborar qual é o propósito dessas duas linhas em trapfunção var args = Array.prototype.slice.call(arguments); var message = args.join(' ');:? Por que você passa os argumentos através disso para a mensagem?
user1555863
1
@ user1555863 Atualizei minha resposta para responder às suas perguntas, consulte a seção abaixo do código.
Walter Stabosz
1
Eu acho que a segunda linha da função "console.clear ()" deve ler "console.raw.length = 0", em vez de "console.row.length = 0".
Steve J
52

Vale ressaltar que console.logno IE8 não é uma verdadeira função Javascript. Não suporta os métodos applyou call.

James Wheare
fonte
3
+1 Este é o meu erro preciso esta manhã. Estou tentando aplicar argumentos ao console.log e o IE8 está me odiando.
Bernhard Hofmann
[piada] A Microsoft diz que "não é seguro permitir que as pessoas sobrescrevam o objeto do console": /
Tom Roggero
1
Eu tenho usado: console.log=Function.prototype.bind.call(console.log,console);para contornar isso.
precisa saber é o seguinte
1
IE8 não tem bind.
katspaugh
44

Supondo que você não se preocupe com um substituto para alertar, aqui está uma maneira ainda mais concisa de solucionar as deficiências do Internet Explorer:

var console=console||{"log":function(){}};
Leif Wickland
fonte
+1 Como eu estou analisando meu código em uma função anônima, colocar o console em uma variável como essa é a melhor solução para mim. Ajuda-me a não interferir com qualquer outra conexão de console acontecendo em outras bibliotecas.
Codesleuth
2
Você deseja iniciar o log assim que as ferramentas do desenvolvedor forem abertas. Se você colocar esta solução em um escopo de vida longa (por exemplo, registra funções internas como retornos de chamada), ela continuará usando o fallback silencioso.
Beni Cherniavsky-Paskin
+ 1 / -1 = 0: +1 porque a solução deve ser mais baseada em impedir que console.logs quebre um site no IE - não usado para depurar ... Se você deseja depurar, basta pressionar f12 e abrir o console: ) -1 porque você deve verificar se o console existe antes de substituí-lo.
1nfiniti
Alguns plugins do IE definem console e console.log, mas como objetos vazios, não como funções.
Lilith River
24

Eu realmente gosto da abordagem postada por "orange80". É elegante porque você pode configurá-lo uma vez e esquecê-lo.

As outras abordagens exigem que você faça algo diferente (sempre chame algo diferente do normal console.log()), o que está apenas pedindo problemas ... Eu sei que acabaria esquecendo.

Eu dei um passo adiante, envolvendo o código em uma função de utilitário que você pode chamar uma vez no início do seu javascript, em qualquer lugar, desde que esteja antes de qualquer log. (Estou instalando isso no produto roteador de dados de eventos da minha empresa. Isso ajudará a simplificar o design entre navegadores de sua nova interface de administração.)

/**
 * 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() {}; }
    }
}
Chris Janicki
fonte
1
Que bom que você gostou :-) Eu o uso pelo motivo exato que você menciona - b / c é uma boa segurança. É muito fácil colocar algumas instruções "console.log" em seu código para desenvolvimento e esquecer de removê-las mais tarde. Pelo menos, se você fizer isso e colocá-lo no topo de todos os arquivos em que você usa o console.log, nunca haverá a interrupção do site nos navegadores dos clientes porque eles falham no console.log. Me salvou antes! Melhorias agradáveis, btw :-)
jpswain
1
"É muito fácil ... esquecer de removê-los". Uma coisa útil que sempre faço no log de depuração temporário é o prefixo do código com um comentário vazio, /**/console.log("...");para facilitar a pesquisa e a localização do código temporário.
Lawrence Dol
8

Se você ficar "indefinido" em todas as chamadas do console.log, isso provavelmente significa que você ainda tem um firebuglite antigo carregado (firebug.js). Ele substituirá todas as funções válidas do console.log do IE8, mesmo que elas existam. Foi o que aconteceu comigo de qualquer maneira.

Verifique se há outro código substituindo o objeto do console.

user168290
fonte
5

A melhor solução para qualquer navegador sem console é:

// 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;
        }
    }
}());
Vinícius Moraes
fonte
1
Isso tem o problema evidente de que os objetos ou seqüências de caracteres registrados usando console.group ou console.GroupCollapsed desaparecerão completamente. Isso é desnecessário, eles devem ser mapeados para console.log, se disponível.
21913 Ben
3

Existem tantas respostas. Minha solução para isso foi:

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

Em resumo, se console.log não existir (ou, nesse caso, não estiver aberto), armazene o log em um espaço de nomes global Array. Dessa forma, você não será incomodado com milhões de alertas e ainda poderá visualizar seus logs com o console do desenvolvedor aberto ou fechado.

calcazar
fonte
2
if (window.console && 'function' === tipo de window.console.log) {
    window.console.log (o);
}
Balázs Németh
fonte
Você está dizendo que window.console.log()pode estar disponível no IE8 mesmo quando console.log()não estiver?
Larsh
O problema aqui é que typeof window.console.log === "object", não"function"
Isócrono
2

Aqui está o meu "IE, por favor, não bata"

typeof console=="undefined"&&(console={});typeof console.log=="undefined"&&(console.log=function(){});
BrunoLM
fonte
1

Encontrei isso no 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
fonte
1

Estou usando a abordagem de Walter de cima (consulte: https://stackoverflow.com/a/14246240/3076102 )

Eu misturo uma solução que encontrei aqui https://stackoverflow.com/a/7967670 para mostrar corretamente os objetos.

Isso significa que a função de interceptação se torna:

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 />'));
        }
    }
} 

Espero que isto seja útil:-)

Raymond Elferink
fonte
0

Funciona no IE8. Abra as Ferramentas de desenvolvedor do IE8 pressionando F12.

>>console.log('test')
LOG: test
Konstantin Tarkus
fonte
6
Isso emite "indefinido" no meu caso.
Acme
6
Como o Sr. Lucky apontou: "o console.log está disponível apenas após a abertura das Ferramentas do Desenvolvedor (F12 para alternar entre abrir e fechar)."
O Silencer
0

Eu gosto deste método (usando o documento do jquery pronto) ... ele permite que você use o console, mesmo no ie ... só é necessário recarregar a página se você abrir as ferramentas de desenvolvimento do ie, após o carregamento da página ...

poderia ser mais lento, contabilizando todas as funções, mas eu só uso log, então é isso que faço.

//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
        }})();
    }
});
user3560902
fonte
0

Aqui está uma versão que fará logon no console quando as ferramentas do desenvolvedor estiverem abertas e não quando estiverem fechadas.

(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
fonte
Bom que seu escopo seja limitado, poderia suportar o caso quando o IE8 DevTools estiver aberto no meio da execução do código, mas não funcionar no IE8, console.log é um objeto, portanto, não possui applymétodo.
Nishi
0

Crie seu próprio console em html .... ;-) Isso pode ser melhorado, mas você pode começar com:

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);
        }
    };
}
Alexandre Assouad
fonte