javascript 属性查找与 dom 原型链本质相同,均沿 proto 链向上回溯:先查自身属性,再逐级查找 htmldivelement.prototype → htmlelement.prototype → element.prototype → node.prototype → eventtarget.prototype → object.prototype,最终至 null。

JavaScript 中的属性查找机制,和 DOM 元素的原型链,本质是同一套规则在不同对象上的体现——都是沿着 __proto__ 链向上逐级查找,直到 null。
属性查找机制:就近原则 + 向上回溯
当你访问一个对象的属性或方法时,JS 不会直接去原型上找,而是按固定顺序搜索:
- 先查对象自身(own property),存在就返回;
- 没找到,就去
obj.__proto__(即构造函数的prototype)中找; - 还没找到,继续顺着
__proto__往上跳,比如HTMLDivElement.prototype → HTMLElement.prototype → Element.prototype → Node.prototype → EventTarget.prototype → Object.prototype; - 最终到
Object.prototype.__proto__ === null,停止查找,返回undefined。
这个过程不依赖代码写在哪,只取决于对象的内部原型链接。例如 document.getElementById('box').toString() 能用,是因为 Element 实例没有 toString,但一路向上找到了 Object.prototype.toString。
DOM 元素天然嵌套在标准原型链中
每个 DOM 元素(如 <div>)都是浏览器内置构造函数(如 <code>HTMLDivElement)的实例,它的原型链不是随意拼接的,而是严格遵循规范定义的继承路径:
div.__proto__ === HTMLDivElement.prototypeHTMLDivElement.prototype.__proto__ === HTMLElement.prototypeHTMLElement.prototype.__proto__ === Element.prototypeElement.prototype.__proto__ === Node.prototypeNode.prototype.__proto__ === EventTarget.prototypeEventTarget.prototype.__proto__ === Object.prototypeObject.prototype.__proto__ === null
这意味着你调用 div.addEventListener、div.appendChild、div.nodeType,其实分别来自 EventTarget、Node 和 Node 原型,而不是 HTMLDivElement 自身定义的。
为什么 DOM 方法能跨元素通用?
因为很多核心操作被定义在更上层的原型上:
-
nodeType、parentNode、childNodes来自Node.prototype,所以所有节点类型(Element、Text、Comment 等)都可用; -
getAttribute、setAttribute在Element.prototype,所有 HTML/XML 元素共享; -
addEventListener、dispatchEvent定义在EventTarget.prototype,所以不仅元素支持,document、window、XMLHttpRequest也都能用。
这种设计让 DOM API 既分层清晰,又避免重复实现——底层共性抽到高阶原型,具体类型只补充差异化逻辑。
实际开发中的注意点
理解这套链路,能帮你避开常见误区:
- 不要误以为
div.innerHTML是HTMLDivElement独有,它其实在Element.prototype上; - 扩展 DOM 原型(如给
Element.prototype加方法)会影响所有元素,需谨慎; - 检查某个方法是否存在,不能只看实例,要确认它落在哪一级原型上(可用
console.dir(div)展开查看__proto__链); -
instanceof判断依赖的就是这条原型链,比如div instanceof Element成立,是因为Element.prototype在div.__proto__链上。











