Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

javascript

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.

like image 723
D. Pardal Avatar asked Apr 11 '18 20:04

D. Pardal


1 Answers

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

like image 126
EECOLOR Avatar answered Nov 15 '22 00:11

EECOLOR