„konsola” jest niezdefiniowanym błędem dla Internet Explorer

375

Korzystam z Firebug i mam kilka instrukcji, takich jak:

console.log("...");

na mojej stronie. W IE8 (prawdopodobnie także we wcześniejszych wersjach) pojawiają się błędy skryptu informujące, że „konsola” jest niezdefiniowana. Próbowałem umieścić to na górze mojej strony:

<script type="text/javascript">
    if (!console) console = {log: function() {}};
</script>

wciąż dostaję błędy. W jakikolwiek sposób pozbyć się błędów?

użytkownik246114
źródło
4
Użyj typeofw swoim, jeśli pozwoli uniknąć niezdefiniowanych błędów: if(typeof console === "undefined") { var console = { log: function (logMsg) { } }; }
Flak DiNenno
21
console.log () działa tylko wtedy, gdy narzędzie deweloperskie IE jest otwarte (tak IE jest kiepski). patrz stackoverflow.com/questions/7742781/...
Adrien Be
1
Najlepsza odpowiedź na to pytanie to stackoverflow.com/a/16916941/2274855
Vinícius Moraes,
1
@Aprillion link jest uszkodzony, użyj tego zamiast tego: github.com/h5bp/html5-boilerplate/blob/master/src/js/plugins.js
Alfred Bez

Odpowiedzi:

378

Próbować

if (!window.console) console = ...

Nieokreślona zmienna nie może być bezpośrednio przywołana. Jednak wszystkie zmienne globalne są atrybutami o tej samej nazwie w kontekście globalnym ( windoww przypadku przeglądarek), a dostęp do niezdefiniowanego atrybutu jest w porządku.

Lub użyj, if (typeof console === 'undefined') console = ...jeśli chcesz uniknąć magicznej zmiennej window, zobacz odpowiedź @Tim Down .

kennytm
źródło
160
Żeby było jasne dla innych osób korzystających z tego, umieść <script type="text/javascript"> if (!window.console) console = {log: function() {}}; </script>na górze strony! Dzięki, Kenny.
windowsgm
11
A co zvar console = console || { log: function() {} };
devlord
9
@lorddev Aby użyć tego skrótu, musisz dołączyć window:var console = window.console || { log: function() {} };
jlengstorf
64
Cholera ... budujesz fajną stronę internetową, rozwijając ją dla swojej ulubionej przeglądarki. Na koniec spędzasz 4-5 GODZIN, dzięki czemu jest kompatybilny ze wszystkimi innymi NOWOCZESNYMI przeglądarkami, a następnie spędzasz 4-5 DNI, czyniąc go kompatybilnym z IE.
Izrael
6
Problem z tą odpowiedzią polega na tym, że jeśli używasz innej nazwy, takiej jak debugowanie, ostrzeganie, liczenie w przeglądarce, w której brak konsoli zgłosi wyjątek. Zobacz lepszy sposób, aby to zrobić stackoverflow.com/a/16916941/2274855
Vinícius Moraes
319

Wklej następujące elementy u góry JavaScript (przed użyciem konsoli):

/**
 * Protect window.console method calls, e.g. console is not defined on IE
 * unless dev tools are open, and IE doesn't define console.debug
 * 
 * Chrome 41.0.2272.118: debug,error,info,log,warn,dir,dirxml,table,trace,assert,count,markTimeline,profile,profileEnd,time,timeEnd,timeStamp,timeline,timelineEnd,group,groupCollapsed,groupEnd,clear
 * Firefox 37.0.1: log,info,warn,error,exception,debug,table,trace,dir,group,groupCollapsed,groupEnd,time,timeEnd,profile,profileEnd,assert,count
 * Internet Explorer 11: select,log,info,warn,error,debug,assert,time,timeEnd,timeStamp,group,groupCollapsed,groupEnd,trace,clear,dir,dirxml,count,countReset,cd
 * Safari 6.2.4: debug,error,log,info,warn,clear,dir,dirxml,table,trace,assert,count,profile,profileEnd,time,timeEnd,timeStamp,group,groupCollapsed,groupEnd
 * Opera 28.0.1750.48: debug,error,info,log,warn,dir,dirxml,table,trace,assert,count,markTimeline,profile,profileEnd,time,timeEnd,timeStamp,timeline,timelineEnd,group,groupCollapsed,groupEnd,clear
 */
(function() {
  // Union of Chrome, Firefox, IE, Opera, and Safari console methods
  var methods = ["assert", "cd", "clear", "count", "countReset",
    "debug", "dir", "dirxml", "error", "exception", "group", "groupCollapsed",
    "groupEnd", "info", "log", "markTimeline", "profile", "profileEnd",
    "select", "table", "time", "timeEnd", "timeStamp", "timeline",
    "timelineEnd", "trace", "warn"];
  var length = methods.length;
  var console = (window.console = window.console || {});
  var method;
  var noop = function() {};
  while (length--) {
    method = methods[length];
    // define undefined methods as noops to prevent errors
    if (!console[method])
      console[method] = noop;
  }
})();

Opakowanie funkcji służy do zawężenia zakresu zmiennych, aby nie definiować żadnych zmiennych. Chroni to przed niezdefiniowanymi consolei niezdefiniowanymi console.debug(i innymi brakującymi metodami).

EDYCJA: Zauważyłem, że HTML5 Boilerplate używa podobnego kodu w pliku js / plugins.js, jeśli szukasz rozwiązania, które (prawdopodobnie) będzie aktualizowane.

Peter Tseng
źródło
14
Dlaczego ta odpowiedź ma tak mało pozytywnych opinii? Jest to najbardziej kompletny z tych opublikowanych tutaj.
mavilein
Z powodu daty. Absolutnie zgadzaj się z odpowiednimi działającymi rozwiązaniami. Myślę, że ten temat wymaga moderacji. Przepraszam, za słaby angielski.
woto
Całkiem kompletne, z wyjątkiem tego, że nie będzie próbował przekierować logowania do funkcji dziennika (jeśli jest dostępna), więc wszystkie dzienniki zostaną utracone
Christophe Roussy
5
Kiedy to się dokładnie stanie? Ten kod powinien definiować tylko elementy, które nie są jeszcze zdefiniowane.
Peter Tseng,
4
Myślę, że tak czy inaczej - (funkcja () {...} ()) lub (funkcja () {...}) () - działa właściwie
Peter Tseng
73

Inną alternatywą jest typeofoperator:

if (typeof console == "undefined") {
    this.console = {log: function() {}};
}

Jeszcze inną alternatywą jest użycie biblioteki rejestrowania, takiej jak mój własny log4javascript .

Tim Down
źródło
Jednak dobrym pomysłem byłoby zmienić niezadeklarowane zadanie na odpowiednią deklarację.
kangax
1
Masz na myśli używanie var? To tylko myliłoby rzeczy tutaj. A może chodzi Ci window.consoleraczej o przypisanie do niż console?
Tim Down
Korzystanie var. Dlaczego miałoby to wprowadzać w błąd?
kangax
2
Co za myląca dyskusja. +1 do oryginalnej odpowiedzi. Gdybym mógł dać +2, podałbym link do twojego własnego log4javascript. Dzięki, OP!
Jay Taylor
8
@yckart: Nie. typeofGwarantowane jest zwrócenie ciągu znaków i "undefined"jest to ciąg znaków. Gdy dwa operandy są tego samego typu ==i ===zostały określone tak, aby wykonywać dokładnie te same kroki. Użycie typeof x == "undefined"to solidny sposób na sprawdzenie, czy xjest niezdefiniowany w jakimkolwiek zakresie i w dowolnym środowisku zgodnym z ECMAScript 3.
Tim Down
47

Aby uzyskać bardziej niezawodne rozwiązanie, użyj tego fragmentu kodu (wziętego z kodu źródłowego Twittera):

// 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
źródło
13

W moich skryptach używam skrótu:

window.console && console.log(...) // only log if the function exists

lub, jeśli nie jest możliwa lub niewykonalna edycja każdej linii console.log, tworzę fałszywą konsolę:

// check to see if console exists. If not, create an empty object for it,
// then create and empty logging function which does nothing. 
//
// REMEMBER: put this before any other console.log calls
!window.console && (window.console = {} && window.console.log = function () {});
iblamefish
źródło
2
Błąd składni. Dlaczego nie tylkoif(!console) {console = {} ; console.log = function(){};}
Meekohi
1
Lub nie tylko!window.console && (window.console = { log: function () { } });
Maksim Vi.
10

Możesz użyć, console.log()jeśli masz Developer Toolsotwarty w IE8, a także możesz użyć pola Consoletekstowego na karcie skryptu.


źródło
7
Nie jest to dobre, jeśli zapomnisz zamienić kod konsoli. Błąd w IE8 uniemożliwi działanie kodu JS
yunzen
7
if (typeof console == "undefined") {
  this.console = {
    log: function() {},
    info: function() {},
    error: function() {},
    warn: function() {}
  };
}
insygnia
źródło
1
zastrzeżenie emptor: należy to zdefiniować na poziomie globalnym, do którego się thisodnosi window.
Sgnl
7

Na podstawie dwóch poprzednich odpowiedzi autorstwa

oraz dokumentacje dotyczące

Oto implementacja najlepszych starań dla tego problemu, co oznacza, że ​​jeśli istnieje plik console.log, to uzupełnia luki w nieistniejących metodach za pomocą console.log.

Na przykład dla IE6 / 7 możesz zastąpić rejestrowanie alertem (głupie, ale działa), a następnie dołączyć poniższego potwora (nazwałem to console.js): [Możesz swobodnie usuwać komentarze według własnego uznania, zostawiłem je w celach informacyjnych, minimizer może sobie z nimi poradzić]:

<!--[if lte IE 7]>
<SCRIPT LANGUAGE="javascript">
    (window.console = window.console || {}).log = function() { return window.alert.apply(window, arguments); };
</SCRIPT>
<![endif]-->
<script type="text/javascript" src="console.js"></script>

i console.js:

    /**
     * Protect window.console method calls, e.g. console is not defined on IE
     * unless dev tools are open, and IE doesn't define console.debug
     */
    (function() {
        var console = (window.console = window.console || {});
        var noop = function () {};
        var log = console.log || noop;
        var start = function(name) { return function(param) { log("Start " + name + ": " + param); } };
        var end = function(name) { return function(param) { log("End " + name + ": " + param); } };

        var methods = {
            // Internet Explorer (IE 10): http://msdn.microsoft.com/en-us/library/ie/hh772169(v=vs.85).aspx#methods
            // assert(test, message, optionalParams), clear(), count(countTitle), debug(message, optionalParams), dir(value, optionalParams), dirxml(value), error(message, optionalParams), group(groupTitle), groupCollapsed(groupTitle), groupEnd([groupTitle]), info(message, optionalParams), log(message, optionalParams), msIsIndependentlyComposed(oElementNode), profile(reportName), profileEnd(), time(timerName), timeEnd(timerName), trace(), warn(message, optionalParams)
            // "assert", "clear", "count", "debug", "dir", "dirxml", "error", "group", "groupCollapsed", "groupEnd", "info", "log", "msIsIndependentlyComposed", "profile", "profileEnd", "time", "timeEnd", "trace", "warn"

            // Safari (2012. 07. 23.): https://developer.apple.com/library/safari/#documentation/AppleApplications/Conceptual/Safari_Developer_Guide/DebuggingYourWebsite/DebuggingYourWebsite.html#//apple_ref/doc/uid/TP40007874-CH8-SW20
            // assert(expression, message-object), count([title]), debug([message-object]), dir(object), dirxml(node), error(message-object), group(message-object), groupEnd(), info(message-object), log(message-object), profile([title]), profileEnd([title]), time(name), markTimeline("string"), trace(), warn(message-object)
            // "assert", "count", "debug", "dir", "dirxml", "error", "group", "groupEnd", "info", "log", "profile", "profileEnd", "time", "markTimeline", "trace", "warn"

            // Firefox (2013. 05. 20.): https://developer.mozilla.org/en-US/docs/Web/API/console
            // debug(obj1 [, obj2, ..., objN]), debug(msg [, subst1, ..., substN]), dir(object), error(obj1 [, obj2, ..., objN]), error(msg [, subst1, ..., substN]), group(), groupCollapsed(), groupEnd(), info(obj1 [, obj2, ..., objN]), info(msg [, subst1, ..., substN]), log(obj1 [, obj2, ..., objN]), log(msg [, subst1, ..., substN]), time(timerName), timeEnd(timerName), trace(), warn(obj1 [, obj2, ..., objN]), warn(msg [, subst1, ..., substN])
            // "debug", "dir", "error", "group", "groupCollapsed", "groupEnd", "info", "log", "time", "timeEnd", "trace", "warn"

            // Chrome (2013. 01. 25.): https://developers.google.com/chrome-developer-tools/docs/console-api
            // assert(expression, object), clear(), count(label), debug(object [, object, ...]), dir(object), dirxml(object), error(object [, object, ...]), group(object[, object, ...]), groupCollapsed(object[, object, ...]), groupEnd(), info(object [, object, ...]), log(object [, object, ...]), profile([label]), profileEnd(), time(label), timeEnd(label), timeStamp([label]), trace(), warn(object [, object, ...])
            // "assert", "clear", "count", "debug", "dir", "dirxml", "error", "group", "groupCollapsed", "groupEnd", "info", "log", "profile", "profileEnd", "time", "timeEnd", "timeStamp", "trace", "warn"
            // Chrome (2012. 10. 04.): https://developers.google.com/web-toolkit/speedtracer/logging-api
            // markTimeline(String)
            // "markTimeline"

            assert: noop, clear: noop, trace: noop, count: noop, timeStamp: noop, msIsIndependentlyComposed: noop,
            debug: log, info: log, log: log, warn: log, error: log,
            dir: log, dirxml: log, markTimeline: log,
            group: start('group'), groupCollapsed: start('groupCollapsed'), groupEnd: end('group'),
            profile: start('profile'), profileEnd: end('profile'),
            time: start('time'), timeEnd: end('time')
        };

        for (var method in methods) {
            if ( methods.hasOwnProperty(method) && !(method in console) ) { // define undefined methods as best-effort methods
                console[method] = methods[method];
            }
        }
    })();
TWiStErRob
źródło
Nie jestem pewien, czy potrzebujemy methods.hasOwnProperty(method) && w pętli for.
TWiStErRob
Jestem pewien, że tego potrzebujesz.
ErikE
Zrobiłem szybki test w konsoli Chrome: > x = { a: 1, b: 2}-> Object {a: 1, b: 2}i for(var f in x) {console.log(f + " " + x[f]);} 'end'-> a 1 b 2 "end". Tak więc utworzony obiekt anonimowy nie ma żadnych dodatkowych właściwości i methodsjest po prostu tworzony przed forpętlą. Czy można zhakować powyższe?
TWiStErRob
3
Tak. var x = { a: 1, b: 2}; Object.prototype.surprise = 'I\'m in yer objectz'; for (var f in x) {console.log(f, x[f]);}Nigdy nie wiadomo, co biblioteka zrobiła z obiektami w łańcuchu dziedziczenia obiektu, z którym pracujesz. Dlatego zaleca się stosowanie narzędzi jakości kodu javascript, takich jak jshint i jslint hasOwnProperty.
ErikE
6

W IE9, jeśli konsola nie jest otwarta, ten kod:

alert(typeof console);

pokaże „obiekt”, ale ten kod

alert(typeof console.log);

wyrzuci wyjątek TypeError, ale nie zwróci niezdefiniowanej wartości;

Tak więc gwarantowana wersja kodu będzie wyglądać podobnie do tego:

try {
    if (window.console && window.console.log) {
        my_console_log = window.console.log;
    }
} catch (e) {
    my_console_log = function() {};
}
bonbonez
źródło
6

Używam tylko console.log w moim kodzie. Dołączam więc bardzo krótki 2 liniowiec

var console = console || {};
console.log = console.log || function(){};
Ruben Decrop
źródło
1
Jak działa .. Nie widzę żadnej linii console.log wydrukowanej w przeglądarce IE, testowałem z 2 różnymi systemami, w których w 1 - console.log działa, a 2 system nie. Próbowałem w obu, ale nie widziałem żadnego dziennika w obu systemach.
kiran
2

Zauważyłem, że OP używa Firebug z IE, więc załóżmy, że to Firebug Lite . Jest to dziwna sytuacja, gdy konsola zostaje zdefiniowana w IE, gdy okno debugera jest otwarte, ale co się stanie, gdy Firebug już działa? Nie jestem pewien, ale być może metoda „firebugx.js” może być dobrym sposobem na przetestowanie w tej sytuacji:

źródło:

https://code.google.com/p/fbug/source/browse/branches/firebug1.2/lite/firebugx.js?r=187

    if (!window.console || !console.firebug) {
        var names = [
            "log", "debug", "info", "warn", "error", "assert",
            "dir","dirxml","group","groupEnd","time","timeEnd",
            "count","trace","profile","profileEnd"
        ];
        window.console = {};
        for (var i = 0; i < names.length; ++i)
            window.console[names[i]] = function() {}
    }

(zaktualizowane linki 12/2014)

Roberto
źródło
1

Używam fauxconsole ; Zmodyfikowałem trochę css, aby wyglądał ładniej, ale działa bardzo dobrze.

Stijn Geukens
źródło
1

Aby debugować w IE, sprawdź ten log4javascript

Praveen
źródło
Jest to świetne, zwłaszcza że moja konsola IE8 niczego nie wyświetla.
Firsh - LetsWP.io
1
@Firsh Dzięki za komentarze.
Praveen
1
Szukałem tutaj komentarza do innego pytania, które brzmiało „bezwstydna autopromocja”, czy też nie wiem - podobnie - ktoś, kto powiedział, że stworzył ten scipt, prawda? Już zamknąłem tę kartę. W każdym razie jest to naprawdę świetne narzędzie i bardzo przydatne w moim projekcie.
Firsh - LetsWP.io
1
@Firsh Nie stworzyłem tego skryptu, jestem osobą taką, jak Ty, korzystając z narzędzia.
Praveen
1

W przypadku obsługi IE8 lub konsoli ograniczonej do console.log (bez debugowania, śledzenia, ...) możesz wykonać następujące czynności:

  • Jeśli nie zdefiniowano konsoli LUB konsoli.log: Utwórz funkcje zastępcze dla funkcji konsoli (śledzenie, debugowanie, rejestr, ...)

    window.console = { debug : function() {}, ...};

  • W przeciwnym razie, jeśli zdefiniowano plik console.log (IE8) ORAZ plik console.debug (dowolny inny) nie jest zdefiniowany: przekieruj wszystkie funkcje rejestrowania do pliku console.log, co pozwoli zachować te dzienniki!

    window.console = { debug : window.console.log, ...};

Nie jestem pewien co do obsługi asertu w różnych wersjach IE, ale wszelkie sugestie są mile widziane. Tutaj także opublikowałem tę odpowiedź: Jak korzystać z logowania do konsoli w Internet Explorerze?

Christophe Roussy
źródło
1
console = console || { 
    debug: function(){}, 
    log: function(){}
    ...
}
David Glass
źródło
1

Skrót konsoli w TypeScript:

if (!window.console) {
console = {
    assert: () => { },
    clear: () => { },
    count: () => { },
    debug: () => { },
    dir: () => { },
    dirxml: () => { },
    error: () => { },
    group: () => { },
    groupCollapsed: () => { },
    groupEnd: () => { },
    info: () => { },
    log: () => { },
    msIsIndependentlyComposed: (e: Element) => false,
    profile: () => { },
    profileEnd: () => { },
    select: () => { },
    time: () => { },
    timeEnd: () => { },
    trace: () => { },
    warn: () => { },
    }
};
devi
źródło
0

Możesz skorzystać z poniższych, aby uzyskać dodatkowy stopień ubezpieczenia, który obejmuje wszystkie podstawy. typeofPierwsze użycie pozwoli uniknąć undefinedbłędów. Użycie ===spowoduje również, że nazwa typu będzie w rzeczywistości ciągiem „niezdefiniowany”. Na koniec będziesz chciał dodać parametr do podpisu funkcji (wybrałem logMsgarbitralnie), aby zapewnić spójność, ponieważ do funkcji dziennika przekazujesz wszystko, co chcesz wydrukować w konsoli. Dzięki temu masz dokładną inteligencję i unikasz wszelkich ostrzeżeń / błędów w twoim IDE świadomym JS.

if(!window.console || typeof console === "undefined") {
  var console = { log: function (logMsg) { } };
}
Flak DiNenno
źródło
0

Wystąpił podobny problem z uruchomieniem pliku console.log w oknach podrzędnych w IE9, utworzonych przez funkcję window.open.

Wygląda na to, że w tym przypadku konsola jest zdefiniowana tylko w oknie nadrzędnym i jest niezdefiniowana w oknach podrzędnych, dopóki ich nie odświeżysz. To samo dotyczy dzieci okien potomnych.

Rozwiązuję ten problem, zawijając następną funkcję w dzienniku (poniżej znajduje się fragment modułu)

getConsole: function()
    {
        if (typeof console !== 'undefined') return console;

        var searchDepthMax = 5,
            searchDepth = 0,
            context = window.opener;

        while (!!context && searchDepth < searchDepthMax)
        {
            if (typeof context.console !== 'undefined') return context.console;

            context = context.opener;
            searchDepth++;
        }

        return null;
    },
    log: function(message){
        var _console = this.getConsole();
        if (!!_console) _console.log(message);
    }
Max Venediktov
źródło
-2

Po tak wielu problemach z tym problemem (ciężko jest debugować błąd, ponieważ jeśli otworzysz konsolę programisty, błąd już się nie zdarza!) Postanowiłem stworzyć kod przepełnienia, aby nigdy więcej się tym nie przejmować:

if (typeof window.console === "undefined")
    window.console = {};

if (typeof window.console.debug === "undefined")
    window.console.debug= function() {};

if (typeof window.console.log === "undefined")
    window.console.log= function() {};

if (typeof window.console.error === "undefined")
    window.console.error= function() {alert("error");};

if (typeof window.console.time === "undefined")
    window.console.time= function() {};

if (typeof window.console.trace === "undefined")
    window.console.trace= function() {};

if (typeof window.console.info === "undefined")
    window.console.info= function() {};

if (typeof window.console.timeEnd === "undefined")
    window.console.timeEnd= function() {};

if (typeof window.console.group === "undefined")
    window.console.group= function() {};

if (typeof window.console.groupEnd === "undefined")
    window.console.groupEnd= function() {};

if (typeof window.console.groupCollapsed === "undefined")
    window.console.groupCollapsed= function() {};

if (typeof window.console.dir === "undefined")
    window.console.dir= function() {};

if (typeof window.console.warn === "undefined")
    window.console.warn= function() {};

Osobiście używam tylko console.log i console.error, ale ten kod obsługuje wszystkie inne funkcje przedstawione w sieci Mozzila Developer Network: https://developer.mozilla.org/en-US/docs/Web/API/console . Po prostu umieść ten kod na górze strony i gotowe.

Hoffmann
źródło
-11

Możesz używać console.log (...) bezpośrednio w Firefoksie, ale nie w IE. W IE musisz użyć window.console.

Mohit Kumar
źródło
11
console.log i window.console.log odnoszą się do tej samej funkcji w dowolnej przeglądarce, która jest nawet zdalnie zgodna z ECMAscript. Dobrą praktyką jest używanie tego drugiego, aby uniknąć przypadkowego zasłaniania zmiennej lokalnej przez globalny obiekt konsoli, ale nie ma to absolutnie nic wspólnego z wyborem przeglądarki. console.log działa dobrze w IE8, a AFAIK nie ma w ogóle możliwości rejestrowania w IE6 / 7.
Tgr