console.log.apply не работает в IE9 - PullRequest
47 голосов
/ 04 апреля 2011

Похоже, я заново изобрел колесо, но почему-то это не работает в Internet Explorer 9, но работает в IE6.

function debug()
  if(!window.console) { 
    window.console = { log: function() { /* do something */ } };
  }
  console.log.apply(console, arguments);
}

Связанный: Применить () вопрос для JavaScript

F12 Отладчик говорит мне, что этот «объект» (console.log) не поддерживает метод apply. Это даже не признается как функция? Любые другие указатели или идеи?

Ответы [ 7 ]

93 голосов
/ 04 апреля 2011

Вторая часть ответа Я недавно дал тоже отвечает на этот вопрос.Я не считаю это дубликатом этого, поэтому для удобства я вставлю его здесь:

Объект консоли не является частью какого-либо стандарта и является расширением объектной модели документа,Как и другие объекты DOM, он считается хост-объектом и не обязан наследовать от Object или его методов от Function, как это делают нативные функции и объекты ECMAScript.По этой причине применяются и вызовы не определены в этих методах.В IE 9 большинство объектов DOM были улучшены для наследования от собственных типов ECMAScript.Поскольку инструменты разработчика считаются расширением IE (хотя и встроенным расширением), они явно не получили тех же улучшений, что и остальная часть DOM.

Что бы это ни стоило, вы все еще можетеиспользуйте некоторые методы Function.prototype в консольных методах с небольшой магией bind ():

var log = Function.prototype.bind.call(console.log, console);
log.apply(console, ["this", "is", "a", "test"]);
//-> "thisisatest"

Так что вы можете исправить все методы console для IE 9 втаким же образом:

if (Function.prototype.bind && window.console && typeof console.log == "object"){
    [
      "log","info","warn","error","assert","dir","clear","profile","profileEnd"
    ].forEach(function (method) {
        console[method] = this.bind(console[method], console);
    }, Function.prototype.call);
}

Это заменяет функции "хоста" на собственные функции, которые вызывают функции "хоста".Вы можете заставить его работать в Internet Explorer 8, включив реализации совместимости для Function.prototype.bind и Array.prototype.forEach в свой код, или переписав приведенный выше фрагмент, чтобы включить методы, используемые этимиметоды.

См. также

5 голосов
/ 10 сентября 2012

Есть также способ сделать это Полом Айришем.Это проще, чем некоторые ответы выше, но заставляет журнал всегда выводить массив (даже если был передан только один аргумент):

// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console){
    console.log( Array.prototype.slice.call(arguments) );
  }
};
2 голосов
/ 04 апреля 2011

Некоторые функции хост-объекта IE на самом деле не являются функциями JavaScript и поэтому не имеют apply или call. (alert, например.)

Так что вам придется сделать это трудным путем:

function debug()
  var index;

  if(!window.console) { 
    window.console = { log: function() { /* do something */ } };
  }
  for (index = 0; index < arguments.length; ++index) {
      console.log(arguments[index]);
  }
}
1 голос
/ 03 февраля 2013

Я столкнулся с той же проблемой IE и сделал для нее рутину. Он не так хорош, как все вышеперечисленные реализации, но работает во ВСЕХ современных браузерах.

Я тестировал его с Firefox (Firebug), IE 7,8,9 Chrome и Opera. Он использует зло EVAL, но вам нужно только отладить разработку. После этого вы замените код на debug = function () {};

Итак, вот оно.

С уважением, Ганс

(function(ns) {
  var msgs = [];

  // IE compatiblity
  function argtoarr (args,from) {
    var a = [];
    for (var i = from || 0; i<args.length; i++) a.push(args[i]);
    return a;    
  }

  function log(arg) {
    var params = "", format = "", type , output,
        types = {
            "number" : "%d",
            "object" : "{%o}",
            "array" : "[%o]"
        };
    for (var i=0; i<arg.length; i++) {
        params += (params ? "," : "")+"arg["+i+"]";
        type = types[toType(arg[i])] || "%s";
        if (type === "%d" && parseFloat(arg[i]) == parseInt(arg[i], 10)) type = "%f";
        format += (format ? "," : "")+type;
    }
    // opera does not support string format, so leave it out
    output = "console.log("+(window.opera ? "" : "'%f',".replace("%f",format))+"%p);".replace("%p",params);
    eval(output);
  }

  ns.debug = function () {
    msgs.push(argtoarr(arguments));
    if (console !== undefined) while (msgs.length>0) log(msgs.shift());
  }

})(window);

Упс забыл мою функцию toType, вот она.

function toType(obj) {
    if (obj === undefined) return "undefined";
    if (obj === null) return "null";
    var m = obj.constructor;
    if (!m) return "window";
    m = m.toString().match(/(?:function|\[object)\s*([a-z|A-Z|0-9|_|@]*)/);
    return m[1].toLowerCase();
}
0 голосов
/ 03 октября 2017

Попробуйте:

function log(type) {
  if (typeof console !== 'undefined' && typeof console.log !== 'undefined' &&
    console[type] && Function.prototype.bind) {
    var log = Function.prototype.bind.call(console[type], console);
    log.apply(console, Array.prototype.slice.call(arguments, 1));
  }
}
log('info', 'test', 'pass');
log('error', 'test', 'fail');

Работает для log, debug, info, warn, error, group или groupEnd.

0 голосов
/ 21 января 2013

Причина, по которой я пришел к этому вопросу, заключалась в том, что я пытался «усложнить» функцию console.log для определенного модуля, чтобы получить более локализованную и проницательную отладочную информацию, немного поиграв с аргументами, IE 9 сломал его.

@ Энди Э ответ великолепен и помог мне понять, как подать заявку. Я просто не использую тот же подход для поддержки IE9, поэтому мое решение запускает консоль только в «современных браузерах» (быть современным означает, что браузеры ведут себя так, как я ожидаю =)

var C = function() {
  var args = Array.prototype.slice.call(arguments);
  var console = window.console;
  args[0]  = "Module X: "+args[0];
  if( typeof console == 'object' && console.log && console.log.apply ){
    console.log.apply(console, args);
  }
};
0 голосов
/ 04 апреля 2011

Хорошо, это работает, когда вы пишете это так:

function debug()
  if(!window.console) { 
    window.console = {};
    console.log = function() { /* do something */ };
  }
  console.log.apply(console, arguments);
}

Странное поведение ... но если вы пишете это так, 'console.log' распознается как функция.

...