【问题标题】:console.log.apply not working in IE9console.log.apply 在 IE9 中不起作用
【发布时间】:2011-07-29 04:19:25
【问题描述】:

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

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

相关: Apply() question for javascript

F12 调试器告诉我这个“对象”(console.log)不支持方法“应用”。 它甚至不被认为是一种功能吗? 还有其他的建议或想法吗?

【问题讨论】:

    标签: javascript debugging console internet-explorer-9


    【解决方案1】:

    IE 的一些宿主对象函数并不是真正的 JavaScript 函数,因此没有 applycall。 (例如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]);
      }
    }
    

    【讨论】:

    • 没错。并非 JS 中所有可调用的东西都必须是 Function 对象。
    • 一开始我也是这么想的。但话又说回来,它之前没有定义。
    • @line-o:请注意,您在某些地方使用window.console,而在其他地方使用console。现在,在所有其他条件相同的情况下,这些应该会得出相同的结果,但这是我们正在谈论的 IE,如果它与 console.log 玩魔术游戏,我不会完全感到惊讶。
    • @Tim Down:是的,很像 RegExp 实例的非标准扩展,使它们可以调用。 @TJC,@line-o:console 对象在您第一次启动特定选项卡的开发人员工具之前不存在。
    【解决方案2】:

    好的,这样写就可以了:

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

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

    【讨论】:

    • 查看我对您对我的回答的评论的回复。你的前后矛盾应该没问题,但我敢打赌 IE 正在玩愚蠢的游戏。
    【解决方案3】:

    答案I gave recently 的第二部分也回答了这个问题。我不认为这是一个副本,因此为方便起见,我将其粘贴在这里:

    控制台对象不是任何标准的一部分,它是文档对象模型的扩展。与其他 DOM 对象一样,它被视为宿主对象,不需要从 Object 继承,其方法也不需要从 Function 继承,就像原生 ECMAScript 函数和对象一样。这就是 apply 和 call 在这些方法上未定义的原因。在 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"
    

    因此,您可以以相同的方式修复 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);
    }
    

    这用调用“主机”函数的本机函数替换了“主机”函数。您可以通过在代码中包含Function.prototype.bindArray.prototype.forEach 的兼容性实现,或者重写上面的sn-p 以结合这些方法使用的技术,让它在Internet Explorer 8 中运行。

    另见

    【讨论】:

    • +1 当然,该解决方案确实引入了一个新的依赖项:Function#bind,它必须在尚未完全符合 ECMAScript5 规范的实现中提供...
    • 其实是针对IE6的。但它给了我更深入的洞察力并回答了我的问题,这对我帮助很大。所以,非常感谢@Andy
    • 非常感谢@Andy,我需要这个来让我的框架中的调试器在 MSIE 上工作。我已经在源代码中添加了学分,再次感谢!
    • 执行此操作的简短方法是:function debug() { Function.prototype.apply.call(console.log, console, arguments); },这基本上就是 bind-ing 代码所做的。
    • 我希望我能不止一次地支持这个答案。令人惊讶的信息和帮助!谢谢!
    【解决方案4】:

    还有 Paul Irish 的做法。它比上面的一些答案更简单,但是让 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) );
      }
    };
    

    【讨论】:

    • 感谢您提出他的好方法。
    【解决方案5】:

    我提出这个问题的原因是我试图对特定模块的 console.log 函数进行“刺激”,因此我可以通过使用 IE 9 的参数来获得更多本地化和有洞察力的调试信息把它弄坏了。

    @Andy E 的回答很棒,帮助我了解了很多关于应用的见解。我只是不采用相同的方法来支持 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);
      }
    };
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        试试:

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

        适用于logdebuginfowarnerrorgroupgroupEnd

        【讨论】:

          猜你喜欢
          • 2012-03-05
          • 2018-04-29
          • 2012-02-09
          • 2012-08-02
          • 2014-05-04
          • 2015-10-08
          • 2013-10-29
          • 2017-08-27
          • 1970-01-01
          相关资源
          最近更新 更多