JavaScript:“TypeError:非法调用”但我没有调用任何函数

时间:2018-04-11 20:21:52

标签: javascript

注意:我搜索过这个错误,但我发现的一切都是关于调用函数的。我没有打电话给任何功能。我只是想要访问一个房产。

执行这个简单代码时出现错误:

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>

我不知道为什么会这样。如果我尝试从b ...

的原型获取属性,代码工作正常
var a = document.getElementById("something");
var b = Object.create(a);
console.log( Object.getPrototypeOf(b.baseURI) ) //Works

...还使用普通对象。

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

为什么会这样?对我来说完全是无稽之谈。 MDN说:

  

当试图访问对象的属性时,不仅会在对象上搜索该属性,而且还会在对象的原型,原型的原型等上搜索该属性,直到找到具有匹配名称的属性为止或者到达原型链的末尾。

b的原型链(在第一个例子中)是:

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

Proof

编辑:请注意原型链中的1 st 对象是HTMLParagraphElement。这是正常的,所以这不是问题。 (Image

问题(我认为)是礼仪被复制到主b对象而不仅仅是b的原型。这意味着浏览器在第一个对象中找到匹配的名称并尝试访问它,但它会引发错误。 (Image;点击(...)会导致错误)。

但是,我仍然不明白为什么会发生这种情况,也不知道为什么会抛出错误。

2 个答案:

答案 0 :(得分:1)

此行为是由specification的实现引起的。这些DOM节点就是所谓的“平台对象”,它们实现getter的方式与“普通” javascript稍有不同。

简而言之:没有额外的工作就无法扩展它们。

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

访问baseURI的{​​{1}}时,其b指向this,这不是有效的“平台对象”。这将导致b错误。通过Illegal invocation进行访问确实可行,因为然后它的prototype指向有效的“平台对象” this

对Chrome问题的评论对此进行了更详细的说明,并且在您确实需要时提供了一种解决方法:https://bugs.chromium.org/p/chromium/issues/detail?id=495437#c7

答案 1 :(得分:0)

DOM对象在浏览器中非常特殊地实现。使用像Object.create()这样的通用函数复制其中一个时,结果不会像原始函数一样链接到DOM中。许多属性需要访问DOM,因此当您尝试访问副本中的这些属性时会出现错误。