You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript报错TypeError: Illegal invocation,但未调用任何函数

为什么用Object.create(DOM元素)创建的对象访问属性会报错?

我完全懂你的困惑——明明只是访问个属性,却抛出了和函数调用相关的错误,而且你根本没调用任何函数对吧?这事儿的根源其实和DOM元素的特殊性,以及Object.create()的工作逻辑有关。

问题出在哪?

  • DOM元素可不是普通的JavaScript对象,它们属于宿主对象——是浏览器提供的特殊对象,内部属性的实现逻辑和原生JS对象完全不一样。
  • 当你用Object.create(a)时,是把DOM元素a设成了新对象b的原型。但DOM元素的很多属性(比如baseURI)并不是像普通对象那样直接存储的值,而是通过getter函数来返回结果的。
  • 这些getter函数在设计的时候,默认是绑定在DOM元素实例本身上执行的。当你访问b.baseURI时,JS引擎会顺着原型链找到a上的getter,然后在b的上下文(也就是this指向b)里执行这个getter。但b只是个普通JS对象,不是合法的DOM元素,浏览器就会抛出错误——看起来像是函数调用的问题,但本质是getter执行时的上下文不对。

怎么解决?

根据你的需求,有几种不同的处理方式:

  • 如果只是想把DOM元素的属性复制到一个普通对象上,可以用Object.assign:
    var a = document.getElementById("something");
    var b = Object.assign({}, a);
    console.log(b.baseURI); // 这样就能正常获取属性值了
    
  • 如果需要复制包括不可枚举在内的所有属性,可以用Object.getOwnPropertyDescriptors:
    var a = document.getElementById("something");
    var b = Object.create(null);
    Object.defineProperties(b, Object.getOwnPropertyDescriptors(a));
    console.log(b.baseURI);
    
  • 如果你的目标是创建一个DOM元素的副本(而不是普通对象),那应该用DOM自带的cloneNode方法:
    var a = document.getElementById("something");
    var b = a.cloneNode(true); // true表示深复制,会复制元素的子节点
    console.log(b.baseURI);
    

小提醒

DOM对象的原型链和行为和普通JS对象差异很大,别用操作普通对象的思路去折腾它们。用浏览器提供的DOM API来处理DOM元素,才是最稳妥的做法。

内容的提问来源于stack exchange,提问作者D. Pardal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:57:15