Điều gì đã xảy ra với console.log trong IE8?


254

Theo bài đăng này, nó đã ở bản beta, nhưng nó không có trong bản phát hành?


65
console.log có trong IE8, nhưng consoleđối tượng không được tạo ra cho đến khi bạn mở DevTools. Do đó, một cuộc gọi đến console.logcó thể dẫn đến lỗi, ví dụ nếu nó xảy ra khi tải trang trước khi bạn có cơ hội mở các công cụ dev. Các câu trả lời chiến thắng ở đây giải thích nó một cách chi tiết hơn.
SDC

Câu trả lời:


229

Thậm chí tốt hơn cho dự phòng là:


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


71
Điều này rất không thực tế - làm thế nào bạn có thể gỡ lỗi một trang web bằng thứ gì đó đưa ra cảnh báo cho mỗi cuộc gọi đến console.log (). Điều gì xảy ra nếu bạn có hơn 10 cuộc gọi để đăng nhập () trong mã của bạn. Điều gì nếu tin nhắn là một đối tượng? Câu trả lời của Walter có ý nghĩa hơn nhiều, như một điểm khởi đầu.
Chính xác

7
@Precastic: Mọi người sẽ ngừng sử dụng trình duyệt: P
Amogh Talpallikar 30/03/2016

Xem nhận xét của tôi về câu trả lời của Mister Lucky.
Daniel Schilling

1
một dự phòng thay thế không phô trương (mặc dù không hoàn hảo) là đặt document.title. Ít nhất là nó không khóa trình duyệt với một cảnh báo phương thức.
brennanyoung

257

console.log chỉ khả dụng sau khi bạn đã mở Công cụ dành cho nhà phát triển (F12 để chuyển đổi mở và đóng). Điều thú vị là sau khi bạn mở nó, bạn có thể đóng nó, sau đó vẫn đăng lên nó thông qua các cuộc gọi console.log và chúng sẽ được nhìn thấy khi bạn mở lại nó. Tôi nghĩ rằng đó là một lỗi của các loại, và có thể được sửa chữa, nhưng chúng ta sẽ thấy.

Có lẽ tôi sẽ chỉ sử dụng một cái gì đó như thế này:

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

và thậm chí đơn giản hơn:

function trace(s) {
  try { console.log(s) } catch (e) { alert(s) }
}

11
Dù bằng cách nào bạn cũng không nên gọi console.log một cách mù quáng vì $ các trình duyệt khác có thể không có nó và do đó chết vì lỗi JavaScript. +1
Kent Fredric

8
Dù sao bạn cũng có thể muốn tắt dấu vết trước khi phát hành;)
Kent Fredric

2
Thật ý nghĩa khi không đăng nhập mà không có các công cụ dành cho nhà phát triển được mở, nhưng làm cho nó trở thành một ngoại lệ nếu không thất bại trong âm thầm là quyết định khó hiểu thực sự ở đây.
ehv

4
Tôi muốn chỉ ra một nhược điểm của việc bao bọc console.log như thế này ... bạn sẽ không thấy nữa nơi đăng nhập của bạn đến từ đâu. Tôi thấy rằng đôi khi rất hữu ích khi ở trên đầu nó trông có vẻ sai khi có mọi dòng giao diện điều khiển bắt nguồn từ cùng một vị trí trong mã của bạn.
Martin Westin

2
alertlà xấu xa Một số mã hoạt động khác nhau khi cảnh báo được sử dụng vì tài liệu mất tập trung, khiến lỗi thậm chí khó chẩn đoán hoặc tạo mã hơn ở những nơi không có trước đây. Ngoài ra, nếu bạn vô tình để lại một console.logmã sản xuất, nó là lành tính (giả sử nó không nổ tung) - chỉ cần âm thầm đăng nhập vào bảng điều khiển. Nếu bạn vô tình để lại một alertmã sản xuất, trải nghiệm người dùng sẽ bị hủy hoại.
Daniel Schilling

56

Đây là nhận của tôi về các câu trả lời khác nhau. Tôi thực sự muốn xem các thông điệp đã ghi, ngay cả khi tôi không mở giao diện điều khiển IE khi chúng bị bắn, vì vậy tôi đẩy chúng vào một console.messagesmảng mà tôi tạo. Tôi cũng đã thêm một chức năng console.dump()để tạo điều kiện xem toàn bộ nhật ký. console.clear()sẽ làm trống hàng đợi tin nhắn.

Các giải pháp này cũng "xử lý" các phương thức Bảng điều khiển khác (mà tôi tin rằng tất cả đều bắt nguồn từ API Bảng điều khiển Firebird )

Cuối cùng, giải pháp này ở dạng IIFE , vì vậy nó không gây ô nhiễm phạm vi toàn cầu. Đối số chức năng dự phòng được xác định ở dưới cùng của mã.

Tôi chỉ thả nó trong tệp JS chính của tôi được bao gồm trên mỗi trang và quên nó đi.

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

Một số thông tin thêm

Dòng này var args = Array.prototype.slice.call(arguments);tạo ra một mảng từ argumentsObject. Điều này là bắt buộc vì các đối số không thực sự là một mảng .

trap()là một trình xử lý mặc định cho bất kỳ chức năng API nào. Tôi chuyển các đối số để messagebạn có được nhật ký của các đối số được truyền cho bất kỳ lệnh gọi API nào (không chỉ console.log).

Biên tập

Tôi đã thêm một mảng bổ sung console.rawđể nắm bắt các đối số chính xác như được truyền vào trap(). Tôi nhận ra rằng việc args.join(' ')chuyển đổi các đối tượng thành chuỗi "[object Object]"đôi khi có thể không mong muốn. Cảm ơn bfontaine cho lời đề nghị .


4
+1 Đây là giải pháp duy nhất bắt đầu có ý nghĩa. Trong thế giới nào bạn sẽ không muốn thấy những tin nhắn bạn đang gửi đến bảng điều khiển!
Chính xác

Câu trả lời chính xác. Thực sự thích bài viết IIFE bạn đã đề cập, có lẽ là một trong những bài hay nhất tôi đã đọc cho đến nay. Bạn có thể xin hãy giải thích mục đích cho hai dòng sau trong là những gì trapchức năng: var args = Array.prototype.slice.call(arguments); var message = args.join(' ');? Tại sao bạn chuyển các đối số thông qua điều này cho tin nhắn?
user1555863

1
@ user1555863 Tôi đã cập nhật câu trả lời của mình để trả lời câu hỏi của bạn, xem phần bên dưới mã.
Walter Stabosz

1
Tôi nghĩ dòng thứ hai của hàm "console.clear ()" của bạn nên đọc "console.raw.length = 0", thay vì "console.row.length = 0".
Steve J

52

Điều đáng chú ý là console.logtrong IE8 không phải là một chức năng Javascript thực sự. Nó không hỗ trợ applyhoặc callphương pháp.


3
+1 Đây là lỗi chính xác của tôi sáng nay. Tôi đang cố gắng áp dụng các đối số cho console.log và IE8 đang ghét tôi.
Bernhard Hofmann

[đùa] Microsoft nói "không an toàn cho chúng tôi khi để mọi người ghi đè lên đối tượng bàn điều khiển": /
Tom Roggero

1
Tôi đã sử dụng: console.log=Function.prototype.bind.call(console.log,console);để giải quyết vấn đề này.
mowwwalker

1
IE8 không có bind.
katspaugh

44

Giả sử bạn không quan tâm đến dự phòng để cảnh báo, đây là một cách thậm chí ngắn gọn hơn để khắc phục những thiếu sót của Internet Explorer:

var console=console||{"log":function(){}};

+1 Vì tôi sắp xếp mã của mình trong một hàm ẩn danh, đặt bàn điều khiển vào một biến như thế này là giải pháp tốt nhất cho tôi. Giúp tôi không can thiệp vào bất kỳ giao diện điều khiển nào đang diễn ra trong các thư viện khác.
Codeleuth

2
Bạn muốn bắt đầu đăng nhập ngay khi các công cụ dành cho nhà phát triển đã được mở. Nếu bạn đặt giải pháp này trong phạm vi tồn tại lâu dài (ví dụ: đăng ký các chức năng bên trong dưới dạng gọi lại), thì nó sẽ tiếp tục sử dụng dự phòng im lặng.
Beni Cherniavsky-Paskin

+ 1 / -1 = 0: +1 vì giải pháp nên dựa nhiều hơn vào việc ngăn chặn console.logs phá vỡ một trang web trong IE - không được sử dụng để gỡ lỗi ... Nếu bạn muốn gỡ lỗi, chỉ cần nhấn f12 và mở giao diện điều khiển: ) -1 vì bạn nên kiểm tra xem bàn điều khiển có tồn tại trước khi ghi đè lên nó không.
1nfiniti

Một số plugin IE định nghĩa console và console.log, nhưng là các đối tượng trống, không phải là các chức năng.
Sông Lilith

24

Tôi thực sự thích cách tiếp cận được đăng bởi "cam80". Thật thanh lịch vì bạn có thể đặt nó một lần và quên nó đi.

Các cách tiếp cận khác yêu cầu bạn phải làm một cái gì đó khác biệt (gọi một cái gì đó không phải là đơn giản console.log()mọi lúc), đó chỉ là vấn đề rắc rối mà tôi biết rằng cuối cùng tôi đã quên.

Tôi đã tiến thêm một bước nữa, bằng cách gói mã trong một hàm tiện ích mà bạn có thể gọi một lần khi bắt đầu javascript, bất cứ nơi nào miễn là trước khi đăng nhập. (Tôi đang cài đặt sản phẩm này trong sản phẩm bộ định tuyến dữ liệu sự kiện của công ty tôi. Nó sẽ giúp đơn giản hóa thiết kế trình duyệt chéo của giao diện quản trị viên mới.)

/**
 * 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() {}; }
    }
}

1
Vui mừng bạn thích nó :-) Tôi sử dụng nó cho lý do chính xác mà bạn đề cập - b / c đó là một sự an toàn tốt. Thật quá dễ dàng để đặt một số câu lệnh "console.log" trong mã của bạn để phát triển và quên xóa chúng sau này. Ít nhất nếu bạn làm điều này và đặt nó ở đầu mỗi tệp mà bạn sử dụng console.log, bạn sẽ không bao giờ có trang web phá vỡ trình duyệt của khách hàng vì họ thất bại trên console.log. Cứu tôi trước! Những cải tiến tốt đẹp, btw :-)
jpswain

1
"Thật là quá dễ để ... quên loại bỏ chúng". Một điều hữu ích tôi luôn làm với ghi nhật ký gỡ lỗi tạm thời là tiền tố mã với một nhận xét trống, /**/console.log("...");vì vậy thật dễ dàng để tìm kiếm và định vị mã tạm thời.
Lawrence Dol

8

Nếu bạn nhận được "không xác định" cho tất cả các cuộc gọi console.log của mình, điều đó có thể có nghĩa là bạn vẫn có một fireormslite cũ được tải (fireorms.js). Nó sẽ ghi đè tất cả các chức năng hợp lệ của console.log của IE8 mặc dù chúng tồn tại. Đây là những gì đã xảy ra với tôi anyway.

Kiểm tra mã khác ghi đè lên đối tượng giao diện điều khiển.


5

Giải pháp tốt nhất cho mọi trình duyệt thiếu giao diện điều khiển là:

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

1
Điều này có vấn đề rõ ràng là các đối tượng hoặc chuỗi được ghi lại bằng console.group hoặc console.groupCollapsed sẽ biến mất hoàn toàn. Điều này là không cần thiết, chúng nên được ánh xạ tới console.log, nếu nó khả dụng.
Ben

3

Có rất nhiều câu trả lời. Giải pháp của tôi cho việc này là:

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

Nói tóm lại, nếu console.log không tồn tại (hoặc trong trường hợp này, không được mở) thì lưu trữ nhật ký trong Mảng không gian tên toàn cầu. Bằng cách này, bạn không bị làm phiền với hàng triệu cảnh báo và bạn vẫn có thể xem nhật ký của mình với bảng điều khiển dành cho nhà phát triển được mở hoặc đóng.


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

Bạn đang nói rằng window.console.log()có thể có sẵn trong IE8 ngay cả khi console.log()không?
LarsH

Vấn đề ở đây là typeof window.console.log === "object", không phải"function"
đồng bộ

2

Đây là "IE xin đừng gặp sự cố"

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

1

Tôi tìm thấy điều này trên 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 = {});
    }
} ());

1

Tôi đang sử dụng phương pháp của Walter từ trên cao (xem: https://stackoverflow.com/a/14246240/3076102 )

Tôi trộn vào một giải pháp tôi tìm thấy ở đây https://stackoverflow.com/a/7967670 để hiển thị đúng Đối tượng.

Điều này có nghĩa là chức năng bẫy trở thành:

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

Tôi hy vọng điều này là hữu ích:-)


0

Nó hoạt động trong IE8. Mở Công cụ dành cho nhà phát triển của IE8 bằng cách nhấn F12.

>>console.log('test')
LOG: test

6
Vấn đề này "không xác định" trong trường hợp của tôi.
acme

6
Như Mister Lucky đã chỉ ra: "console.log chỉ khả dụng sau khi bạn đã mở Công cụ dành cho nhà phát triển (F12 để chuyển đổi mở và đóng)."
Bộ giảm thanh

0

Tôi thích phương pháp này (sử dụng tài liệu của jquery sẵn sàng) ... nó cho phép bạn sử dụng bàn điều khiển ngay cả trong ... nghĩa là bạn chỉ cần tải lại trang nếu bạn mở công cụ dev sau khi tải trang ...

nó có thể chậm chạp bằng cách hạch toán tất cả các chức năng, nhưng tôi chỉ sử dụng nhật ký nên đây là những gì tôi làm.

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

0

Đây là một phiên bản sẽ đăng nhập vào bảng điều khiển khi các công cụ dành cho nhà phát triển được mở và không phải khi chúng được đóng.

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

Điều tốt là nó bị giới hạn về phạm vi, có thể hỗ trợ cho trường hợp khi DevTools của IE8 được mở ở giữa quá trình thực thi mã, nhưng nó không hoạt động trong IE8, console.log là một đối tượng, vì vậy nó không có applyphương thức.
Nishi

0

Tạo bảng điều khiển của riêng bạn trong html .... ;-) Điều này có thể bị bỏ qua nhưng bạn có thể bắt đầu với:

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);
        }
    };
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.