console.log.apply not working in IE9
Solution 1
The second part of an answer I gave recently answers this question too. I don't consider this a duplicate of that one so, for convenience, I'll paste it here:
The console object is not part of any standard and is an extension to the Document Object Model. Like other DOM objects, it is considered a host object and is not required to inherit from Object, nor its methods from Function, like native ECMAScript functions and objects do. This is the reason apply and call are undefined on those methods. In IE 9, most DOM objects were improved to inherit from native ECMAScript types. As the developer tools are considered an extension to IE (albeit, a built-in extension), they clearly didn't receive the same improvements as the rest of the DOM.
For what it's worth, you can still use some Function.prototype methods on console methods with a little bind() magic:
var log = Function.prototype.bind.call(console.log, console); log.apply(console, ["this", "is", "a", "test"]); //-> "thisisatest"
So you could fix up all the console
methods for IE 9 in the same manner:
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);
}
This replaces the "host" functions with native functions that call the "host" functions. You can get it working in Internet Explorer 8 by including the compatibility implementations for Function.prototype.bind
and Array.prototype.forEach
in your code, or rewriting the above snippet to incorporate the techniques used by those methods.
See also
-
console.log
typeof is "object" instead of "function" - Microsoft Connect (Live account required)
Solution 2
There is also Paul Irish's way of doing it. It is simpler than some of the answers above, but makes log always output an array (even if only one argument was passed in):
// 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) );
}
};
Solution 3
Several of IE's host object functions aren't really JavaScript functions and so don't have apply
or call
. (alert
, for example.)
So you'll have to do it the hard way:
function debug()
var index;
if(!window.console) {
window.console = { log: function() { /* do something */ } };
}
for (index = 0; index < arguments.length; ++index) {
console.log(arguments[index]);
}
}
Solution 4
I came across the same IE trouble and made a routine for it. It is not as fancy as all the above implementations, but it works in ALL modern browsers.
I tested it with Firefox (Firebug), IE 7,8,9 Chrome and Opera.
It makes use of the evil EVAL, but you will only want to debug in development.
Afterwards you will replace the code with debug = function () {};
So here it is.
Regards, 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);
Oops forgot my toType function, here it is.
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();
}
Related videos on Youtube
line-o
Developer with a heart for design, graphics, quality, testing and usability freelance developer and consultant former senior dev at white label eCommerce former senior dev at commerce plus
Updated on November 28, 2020Comments
-
line-o over 3 years
Looks like I've re-invented the wheel, but somehow this isn't working in Internet Explorer 9, but does in IE6.
function debug() if(!window.console) { window.console = { log: function() { /* do something */ } }; } console.log.apply(console, arguments); }
Related: Apply() question for javascript
F12 Debugger tells me that this "object" (console.log) does not support method 'apply'. Is it not even recognized as a function? Any other pointers or ideas?
-
Tim Down about 13 yearsExactly. Not everything in JS that is callable is required to be a
Function
object. -
line-o about 13 yearsI thought that too, at first. But then again, it wasn't defined before.
-
T.J. Crowder about 13 years@line-o: Note that you're using
window.console
in some places, andconsole
in others. Now, all else being equal, those should come to the same thing, but this is IE we're talking about and I wouldn't be at all surprised if it plays magic games withconsole.log
. -
T.J. Crowder about 13 yearsSee my reply to your comment on my answer. You're being inconsistent in a way that should be fine, but I bet IE is playing silly games.
-
Andy E about 13 years@Tim Down: true, much like the non-standard extension to RegExp instances that makes them callable. @TJC, @line-o: the
console
object doesn't exist until the first time you launch the developer tools for a particular tab. -
T.J. Crowder about 13 years+1 The solution does, of course, introduce a new dependency:
Function#bind
, which one would have to supply on implementations that aren't quite up to ECMAScript5 spec yet... -
Andy E about 13 years@TJC: yeah, that's right - I should have mentioned that this code should be targeted towards IE 9 only :-)
-
line-o about 13 yearsActually, it was targeted at IE6. But it helped me a lot by giving me deeper insight and answered my question. So, thank you very much @Andy
-
Christian almost 13 yearsThanks a bunch @Andy, I needed this to get the debugger in my framework working on MSIE. I've put credits in the source, thanks again!
-
Sophie Alpert over 12 yearsThe short way to do this is:
function debug() { Function.prototype.apply.call(console.log, console, arguments); }
which is essentially what thisbind
-ing code does. -
Andy E over 12 years@Ben: "short way"? Character count puts
bind()
a tad shorter thanapply()
:-) However, the main difference is that your method is natively compatible with IE 8, whereas the compatibility implementation ofbind()
would be required for the method outlined in my answer. -
Sophie Alpert over 12 yearsYes, that's what I meant. :) Also when going through the implementation of
bind
, it wasn't as clear to me what it was doing and how it was avoidingconsole.log.apply
; just wanted to post a comment in case anyone else was confused similarly in the future. -
line-o over 11 yearsThanks, for bringing up his nice approach.
-
KOGI about 11 yearsI wish I could upvote this answer more than once. Amazingly informative and helpful! Thanks!
-
David Harkness almost 11 yearsYou have
bind
andcall
reversed compared to your blog post. I think you mean to bind tocall
rather than callingbind
, i.e., the blog post is reversed. Unfortunately, I don't have IE9 here to test. :( -
Andy E almost 11 years@DavidHarkness: both work in IE9, but the solution I posted here also works for IE8 and lower with a compatibility implementation of
bind()
:-) See the update at the bottom of my blog post. -
jiyinyiyong over 10 yearsBut in Chrome
console.log == "object"
always returnsfalse
, I'm quite wondering if that is correct? -
Andy E over 5 years@OuuGiii done. For future reference, you can edit any answer yourself, or suggest edits that are reviewed by other users if your rep is not high enough.