4

So this works in firefox and opera, but not in chrome or IE.

        window.onload=function(){

            IMS=new Object();
            IMS.putLog=console.log;


            IMS.putLog('IMS Initialized...');

            IMS.putLog('Loading...');
            loadData(userName, passWord);
            IMS.putLog('Loaded...');
        };

Fails with illegal invocation

No idea why? any advice?

Jacob
  • 72,750
  • 22
  • 137
  • 214
Drew
  • 142
  • 1
  • 11

2 Answers2

2

The reason why is when you invoke IMS.putLog, the this variable for the function is IMS; the console.log implementation probably is counting on this being console.

Here's a workaround:

IMS.putLog = console.log.bind(console);

This will ensure that this is console when calling the log function.

Unfortunately, this won't work in IE < 9, or maybe other browsers. I know that bind doesn't work in PhantomJS, if that matters.

Jacob
  • 72,750
  • 22
  • 137
  • 214
1

See this: "Uncaught TypeError: Illegal invocation" in Chrome

Basically, when you reassign console.log it changes the scope. I'm guess it works in Firefox and Opera just on luck.

A better solution would be:

IMS.putLog = function(){
   console.log.apply(console, arguments); //any passed to IMS.putLog will get passed to console.log
};

Same result, just called in the correct scope.

Edit: This should work in all browsers that support console.log Edit2: Brainfart - arguments needs to be applied

Community
  • 1
  • 1
wharding28
  • 1,047
  • 9
  • 13
  • This isn't quite right; `console.log.apply(console, Array.prototype.call(arguments))` might work. If you do `console.log(arguments)`, that will pass the array-like object `arguments` into `console.log` instead of each actual argument. – Jacob Feb 27 '14 at 22:18
  • 1
    Okay, fixed it. `console.log.apply(console,arguments);` works as is. The call to `Array.prototype.call(arguments)` isn't necessary. `apply()` handles `arguments` exactly like an array. – wharding28 Feb 27 '14 at 22:24
  • 1
    Nice that arguments finally works well for *something*. This is definitely a better cross-browser solution until `bind` is better supported. – Jacob Feb 27 '14 at 22:29
  • Haha, yea. I use it all the time. It's really handy for callbacks. I'll do something like `callback.apply( (typeof thisArg == "undefined" ? this : thisArg) , arguments );` where `thisArg` is an optional scope param. – wharding28 Feb 27 '14 at 22:36