D. Pardal
D. Pardal

Reputation: 6587

JavaScript: "TypeError: Illegal invocation" but I'm not calling any function

Note: I've searched for this error, but everything I've found was about calling functions. I'm not calling any function. I'm just trying to access a property.


I get the error when I execute this simple code:

var a = document.getElementById("something");
var b = Object.create(a);
console.log(b.baseURI) //Throws error with any property of a
<p id="something">Hi! I exist just for demo purposes. This error can occur with any element.</p>

I have no idea of why this happens. The code works fine if I try to get the property from the prototype of b...

var a = document.getElementById("something");
var b = Object.create(a);
console.log( Object.getPrototypeOf(b.baseURI) ) //Works

... and also using a normal object.

var a = {foo: "Foo!"};
var b = Object.create(a);
console.log(b.foo) //Works

Why does this happen? It makes no sense to me. MDN says:

When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.

The prototype chain of b (in the first example) is:

HTMLParagraphElement --> HTMLParagraphElement (the actual element object) --> HTMLParagraphElement --> HTMLElement --> Element --> Node --> EventTarget --> Object --> null

(Proof)

EDIT: Note how the 1st object in the proto chain is a HTMLParagraphElement. This is normal, so that's not the problem. (Image)

The problem (i think) is that the proprieties get kinda copied to the main b object and not just to b's prototype. This means that the browser founds a matching name right in the first object and tries to access it, but it throws an error. (Image; clicking the (...) results in error).

However, I still don't understand why this happens nor why the error is thrown.

Upvotes: 8

Views: 4928

Answers (2)

EECOLOR
EECOLOR

Reputation: 11244

This behavior is caused by the implementation of the specification. These DOM nodes are so-called 'platform objects' and the way they implement getters is slightly different from 'normal' javascript.

In short: they can not be extended without extra work.

var a = document.getElementById("something");
var b = Object.create(a);

When the baseURI of b is accessed, its this points to b which is not a valid 'platform object'. This causes the Illegal invocation error. Accessing it through the prototype does work because then its this points to the prototype which is a valid 'platform object'.

This comment on an issue of Chrome explains it in more detail and also supplies a workaround if you really need it: https://bugs.chromium.org/p/chromium/issues/detail?id=495437#c7

Upvotes: 3

Barmar
Barmar

Reputation: 780842

DOM objects are implemented very specially in browsers. When you copy one of them using a generic function like Object.create(), the result isn't linked into the DOM the same way as the original. Many of the properties need to access the DOM, so you get an error when you try to access these properties in the copy.

Upvotes: 0

Related Questions