console.log.apply 在 IE9 中不起作用

IT技术 javascript debugging console internet-explorer-9
2021-03-18 03:02:22

看起来我重新发明了轮子,但不知何故这在 Internet Explorer 9 中不起作用,但在 IE6 中起作用。

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

相关: JavaScript 的 Apply() 问题

F12 调试器告诉我这个“对象”(console.log)不支持方法“apply”。它甚至不被识别为一个函数吗?任何其他指针或想法?

6个回答

我最近给出的答案的第二部分也回答这个问题。我不认为这与那个重复,所以为了方便起见,我将其粘贴在这里:

控制台对象不是任何标准的一部分,而是文档对象模型的扩展。像其他 DOM 对象一样,它被认为是宿主对象,不需要从 Object 继承,也不需要从 Function 继承它的方法,就像原生的 ECMAScript 函数和对象那样。这就是这些方法上未定义 apply 和 call 的原因。在 IE 9 中,大多数 DOM 对象都被改进为继承自原生 ECMAScript 类型。由于开发人员工具被认为是 IE 的扩展(尽管是内置扩展),它们显然没有得到与 DOM 的其余部分相同的改进。

对于它的value,您仍然可以在控制台方法上使用一些 Function.prototype 方法,并带有一点 bind() 魔法:

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

因此,您可以以相同的方式修复IE 9 的所有console方法

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在你的代码,或重写上面的代码中纳入由这些方法所使用的技术。

也可以看看

实际上,它是针对 IE6 的。但它给了我更深入的洞察力并回答了我的问题,这对我帮助很大。所以,非常感谢@Andy
2021-04-17 03:02:22
+1 当然,该解决方案确实引入了一个新的依赖项:Function#bind,必须在尚未完全符合 ECMAScript5 规范的实现上提供该依赖项...
2021-04-18 03:02:22
感谢一堆@Andy,我需要这个来让我的框架中的调试器在 MSIE 上工作。我已经把学分放在源代码中,再次感谢!
2021-04-22 03:02:22
我希望我能不止一次支持这个答案。信息量惊人且乐于助人!谢谢!
2021-04-29 03:02:22
做到这一点的简短方法是:function debug() { Function.prototype.apply.call(console.log, console, arguments); }这本质上就是这个bind-ing 代码所做的。
2021-05-09 03:02:22

还有保罗爱尔兰的做法。它比上面的一些答案更简单,但使 log 始终输出一个数组(即使只传入一个参数):

// 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) );
  }
};
谢谢,提出他的好方法。
2021-04-19 03:02:22

IE 的一些宿主对象函数并不是真正的 JavaScript 函数,因此没有applycallalert例如。)

所以你必须以艰难的方式做到这一点:

function debug()
  var index;

  if(!window.console) { 
    window.console = { log: function() { /* do something */ } };
  }
  for (index = 0; index < arguments.length; ++index) {
      console.log(arguments[index]);
  }
}
确切地。并非 JS 中可调用的所有内容都必须是Function对象。
2021-04-21 03:02:22
@line-o:请注意,您window.console在某些地方和console其他地方使用现在,在所有其他条件相同的情况下,这些应该是相同的,但这是我们正在谈论的 IE 如果它使用console.log.
2021-04-28 03:02:22
@Tim Down:是的,很像 RegExp 实例的非标准扩展,使它们可以调用。@TJC,@line-o:console直到您第一次为特定选项卡启动开发人员工具时,对象才存在。
2021-05-09 03:02:22
一开始我也是这么想的。但话又说回来,它以前没有定义。
2021-05-15 03:02:22

我遇到了同样的 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);

oop忘了我的 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();
}

好的,当你这样写时它会起作用:

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

奇怪的行为……但是如果你这样写,'console.log' 就会被识别为一个函数。

请参阅我对您对我的回答的评论的回复。你在某种程度上不一致应该没问题,但我敢打赌 IE 正在玩愚蠢的游戏。
2021-04-23 03:02:22