Why are certain function calls termed "illegal invocations" in JavaScript?
Asked Answered
I

3

132

For example, if I do this:

var q = document.querySelectorAll;

q('body');

I get an "Illegal invocation" error in Chrome. I can't think of any reason why this is necessary. For one, it's not the case with all native code functions. In fact I can do this:

var o = Object; // which is a native code function

var x = new o();

And everything works just fine. In particular I've discovered this problem when dealing with document and console. Any thoughts?

Immemorial answered 24/5, 2012 at 18:52 Comment(4)
possible duplicate of Why can't one set an alias to document.getElementById()?Elmaleh
possible duplicate of JavaScript function aliasing doesn't seem to workBasrhin
Exact duplicate of "Uncaught TypeError: Illegal invocation" in ChromeCanoe
They're similar, but not the same (only the answer is the same). In one case the OP assigns the function to a free variable and call it (global context), in another case OP assigns the function to an object property and call it (object context). Users come from search engines might not know that.Afeard
P
212

It's because you've lost the "context" of the function.

When you call:

document.querySelectorAll()

the context of the function is document, and will be accessible as this by the implementation of that method.

When you just call q there's no longer a context - it's the "global" window object instead.

The implementation of querySelectorAll tries to use this but it's no longer a DOM element, it's a Window object. The implementation tries to call some method of a DOM element that doesn't exist on a Window object and the interpreter unsurprisingly calls foul.

To resolve this, use .bind in newer versions of Javascript:

var q = document.querySelectorAll.bind(document);

which will ensure that all subsequent invocations of q have the right context. If you haven't got .bind, use this:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}
Panegyric answered 24/5, 2012 at 18:53 Comment(4)
Oh, good call. You're right because I can do: q.apply(document, ['body']); and it works.Immemorial
Note that this does not necessarilty work for builtin functions in IE. For example, console.log does not have an apply method there.Irremissible
@Alnitak: Yep, it works everywhere except for IE and is why you should often just pass arguments normaly, as in function q(x){ return document.querySelectorAll(x); }. Another thing I really like about IE browser objects is that some of them throw an exception just if you try to read a property from them, so you need to test features with if( 'funcname' in browserobject) instead of the usual if(browserobject.funcname)!Irremissible
Excellent answer, I was really confused by this phenomenon, exact same situation as OP.Sinuosity
S
-2

you can use like this :

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);
Sext answered 8/5, 2018 at 3:42 Comment(0)
E
-3

In my case Illegal invocation occurred due to passing undeclared variable to function as argument. Make sure to declare variable before passing to function.

Enwreathe answered 7/8, 2017 at 12:12 Comment(1)
declaring variable won't make sense to this particular case as illegal invocation is happening as dom dependent method is being called out of the context of DOM, because the moment you do q = document.something the something method looses context of documentBrumaire

© 2022 - 2024 — McMap. All rights reserved.