web-dev-qa-db-fra.com

console.log.apply ne fonctionne pas dans IE9

On dirait que j'ai réinventé la roue, mais d'une manière ou d'une autre, cela ne fonctionne pas dans Internet Explorer 9, mais dans IE6.

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

Connexes: Apply () question for javascript

Le débogueur F12 m'indique que cet "objet" (console.log) ne prend pas en charge la méthode 'apply' ..____. Est-il même pas reconnu comme une fonction? D'autres pointeurs ou idées?

46
line-o

La deuxième partie d’une réponse j’ai donné récemment répond également à cette question. Je ne considère pas cela comme un duplicata de celui-ci, donc, pour plus de commodité, je le collerai ici:

L'objet console ne fait partie d'aucune norme et constitue une extension du modèle d'objet de document. Comme d’autres objets DOM, il est considéré comme un objet hôte et il n’est pas nécessaire d’hériter d’Object, ni de ses méthodes à partir de Function, comme le font les fonctions et les objets ECMAScript natifs. C'est la raison pour laquelle appliquer et appeler sont indéfinis sur ces méthodes. Dans IE 9, la plupart des objets DOM ont été améliorés pour hériter des types ECMAScript natifs. Les outils de développement étant considérés comme une extension de IE (bien qu’une extension intégrée), ils n’ont clairement pas bénéficié des mêmes améliorations que le reste du DOM.

Pour ce que cela vaut, vous pouvez toujours utiliser certaines méthodes Function.prototype sur des méthodes console avec un peu de magie bind ():

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

Vous pouvez donc corriger toutes les méthodes consolepour IE 9 de la même manière:

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

Ceci remplace les fonctions "Host" par des fonctions natives appelant les fonctions "Host". Vous pouvez le faire fonctionner dans Internet Explorer 8 en incluant les implémentations de compatibilité pour Function.prototype.bind et Array.prototype.forEach dans votre code ou en réécrivant le fragment de code ci-dessus pour incorporer les techniques utilisées par ces méthodes.

Voir également

92
Andy E

Il y a aussi la manière de Paul Irish de le faire. C'est plus simple que certaines des réponses ci-dessus, mais oblige log à toujours sortir un tableau (même si un seul argument a été passé):

// 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
BishopZ

Plusieurs fonctions d'objet Host d'IE ne sont pas vraiment des fonctions JavaScript et n'ont donc pas apply ou call. (alert, par exemple.)

Vous devrez donc le faire à la dure:

function debug()
  var index;

  if(!window.console) { 
    window.console = { log: function() { /* do something */ } };
  }
  for (index = 0; index < arguments.length; ++index) {
      console.log(arguments[index]);
  }
}
2
T.J. Crowder

Je suis tombé sur le même problème IE et en ai fait une routine… .. Ce n’est pas aussi sophistiqué que toutes les implémentations ci-dessus, mais cela fonctionne dans TOUS les navigateurs modernes.

Je l’ai testé avec Firefox (Firebug), IE 7,8,9 Chrome et Opera . Il utilise le diabolique EVAL, mais vous ne voudrez déboguer que dans le développement . remplacez le code par debug = function () {};

Alors le voici.

Cordialement, Hans

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

Oups j'ai oublié ma fonction toType, la voici.

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();
}
1
Hans Petersen

Essayer:

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

Fonctionne pour log, debug, info, warn, error, group ou groupEnd.

0
Shobhit Sharma

La raison pour laquelle je suis venu à cette question était que j'essayais d '' épicer 'la fonction console.log pour un module spécifique, donc j'aurais des informations de débogage plus localisées et plus perspicaces en jouant un peu avec les arguments, IE 9 l'ont cassé.

@Andy E answer est formidable et m'a aidé avec beaucoup de perspicacité à appliquer. Je n’adopte tout simplement pas la même approche pour prendre en charge IE9; ma solution n’exécute la console que sur des "navigateurs modernes" (étant moderne, quels que soient les navigateurs qui se comportent de la manière que j’attends =)

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
Fabiano Soriani

Ok, ça marche quand tu écris ça:

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

Comportement étrange ... mais si vous écrivez de cette façon, "console.log" est reconnu comme une fonction.

0
line-o