The following snippet will produce an error in Chrome (and Safari) while it works in Firefox.
I'd expect to have 2 numbers shown in javascript console, but in Chrome I only get the first and then an Uncaught TypeError: Illegal invocation
// a generic promise that return a random float
var makePromise = function() {
return $.Deferred().resolve(Math.random());
}
// This works in all browsers
makePromise().then(function(d) {
console.log(d);
});
// This works in firefox only
makePromise().then(console.log);
<script src=".1.1/jquery.min.js"></script>
The following snippet will produce an error in Chrome (and Safari) while it works in Firefox.
I'd expect to have 2 numbers shown in javascript console, but in Chrome I only get the first and then an Uncaught TypeError: Illegal invocation
// a generic promise that return a random float
var makePromise = function() {
return $.Deferred().resolve(Math.random());
}
// This works in all browsers
makePromise().then(function(d) {
console.log(d);
});
// This works in firefox only
makePromise().then(console.log);
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Why is this happening?
Side note: my question is not the same as this question.
Update
Thanks to ments and answer to use console.log
as callback one need to do
makePromise().then(console.log.bind(console));
Share
Improve this question
edited May 23, 2017 at 12:19
CommunityBot
11 silver badge
asked Aug 9, 2015 at 23:43
FabioFabio
19.2k9 gold badges84 silver badges114 bronze badges
4
- Probably some webkit security limitations. – Shomz Commented Aug 9, 2015 at 23:47
-
1
console.log.bind(console)
. Nothing guarantees it's a "static" function. – zerkms Commented Aug 9, 2015 at 23:55 - Related/dupe: log = console.log, throws illegal invocation error – Oriol Commented Aug 10, 2015 at 0:19
-
As @zerkms says,
console.log.bind(console)
. The amazing thing is thatconsole.log
should work in FF. – Roamer-1888 Commented Aug 10, 2015 at 23:41
2 Answers
Reset to default 7In a chromebook I can duplicate the problem as follows:
function do4(cb){ cb(1); cb(2); cb(3); cb(4); }
do4(console.log)
VM1491:2 Uncaught TypeError: Illegal invocation
at do4 (<anonymous>:2:19)
at <anonymous>:2:12
at Object.InjectedScript._evaluateOn (<anonymous>:905:140)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:838:34)
at Object.InjectedScript.evaluate (<anonymous>:694:21)do4 @ VM1491:2(anonymous function) @ VM1552:2InjectedScript._evaluateOn @ VM1288:905InjectedScript._evaluateAndWrap @ VM1288:838InjectedScript.evaluate @ VM1288:694
But this works fine, and indeed points toward the problem:
do4(console.log.bind(console))
VM1491:2 1
VM1491:2 2
VM1491:2 3
VM1491:2 4
Why is that?
In chrome, console
by itself returns an Object
of prototype Console
,
look:
console
Console {} memory: MemoryInfo__proto__: Console
It may seem odd thinking of console
as an Object
, but it is. console
has several other lesser-used methods that are not used as often as console.log
but are documented in MDN Console Docs and Chrome Console Docs
And here we get to a big Javascript-ism that can confuse people:
Javascript methods are unbound methods. That is, the methods are not bound to any particular object.
So console.log
is a function, but it is the function only and does not preserve its binding of this
to console
.
The variable binding is referred to inside a function's code by a magic this
variable, which can be set with function.bind
or function.apply
.
When console.log()
is called, JS does the binding of the function code's this
to the console
object. But when console.log
is merely passed as a function, it does not do the binding, so that other code can use it more flexibly. This behavior is inconvenient with console.log and many other methods, but in some cases adds needed flexibility.
Try utilizing deferred.resolveWith()
// a generic promise that return a random float
var makePromise = function() {
// set `this` to `window.console` ,
// pass arguments within array
return $.Deferred().resolveWith(window.console, [Math.random()]);
}
// This works in all browsers
makePromise().then(console.log)
//.then(function(d) {
// console.log(d);
//});
// This works in firefox only
makePromise().then(console.log);
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js">
</script>