# 定义

DOM 全称(文档对象模型,Document Object Model),它只是一种模型,DOM 规范是对这种模型的描述。它告诉我们该如何对文档进行访问和修改。这种模型适用于 HTML 和 XML 类型的文档。

DOM 模型用一个树结构来表示一个文档,树的每个分支的终点都是一个节点 (node),每个节点都是包含属性和方法的对象 (objects)。DOM 的方法 (methods) 让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。

前端平时常说的 DOM 对象其实是通过 JS 对 DOM 接口的一种实现,DOM 对象就是 JS 对象,也是使用原型继承

# 历史

DOM 曾经使用 Level 来命名,一直到 Level 3,标准文件维护在 w3c 网站 (opens new window)。Level 4 时修改为 DOM Standard,维护在 WHATWG 网站 (opens new window)

# DOM 节点

# 节点层级(hierarchy)

下面这个列表可以用来表示不同类型节点间的层级(继承)关系:

  • EventTarget
    • Window(特殊,单独分析)
    • Node(基础节点类型)
      • Document(DOM Tree 的根节点)
        • HTMLDocument(对 Document 进行了拓展)
        • document(常用,HTMLDocument 的实例)
      • DocumentType(文档类型节点)
      • Attr(属性节点)
      • CharacterData
        • Text
        • Comment
        • CDATASection
      • DocumentFragment
      • Element
        • SVGElement
        • HTMLElement
          • HTMLCanvasElement(注意这个和 SVG 的区别)
          • HTMLInputElement
          • HTMLBodyElement
          • ...(太多了,不一一列举)

详细说明几个重要的节点类型:

  • EventTarget:作为基础的抽象类(构造函数),所有的节点都继承自它,以便所有的节点都支持“事件”。事件的方法绑定在 EventTarget 的 prototype 对象上。
  • Node 类型:DOM Level 1 定义的最基本的节点类型,拥有一些所有节点共有的属性和方法,继承自 EventTarget。
    • 不同类型的节点使用 nodeType 属性来标识,常见的 nodeType:1: 元素节点3: 文本节点9: Document 节点
  • Document 类型:浏览器中网页的根节点,也是 DOM Tree 的根节点,将文档中的其他元素都包含在内。提供了一些文档层面的通用属性与方法。
    • document对象的关系:继承关系,document > HTMLDocument > Document > Nodedocument对象实际上是HTMLDocument()构造函数的实例,每个文档只有一个。
    • 某些属性和方法是 document 特有的,没有局部版本,比如getElementBtId()、domain。
  • Attr:DOM 4 中的 Attr 类型将不再继承 Node 类型,有可能废弃,不建议使用。
  • CharacterData:一个抽象接口,没有这个类型的对象。继承关系:Text/Comment/CDATASection > CharacterData > Node
  • DocumentFragment:文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document 对象使用。不存在与 DOM Tree 中,不会触发 reflow。
  • HTMLElement:HTMLElement 类下面其实就是各个 html 标签对应的类了,几乎每个标签都有自己单独的类,有特定的属性和方法。

我们可以尝试在 Chrome 的控制台打印一个 ul 节点,由此可以来看一下 Chrome 是如何处理节点间的继承关系的。

# 一个 ul 节点在浏览器控制台输出的内容(简化版)
nodeName: "UL",
nodeType: 1,
nodeValue: null,
...
[[prototype]]: HTMLUListElement
  constructor: HTMLUListElement()
  ...
  # 特定的 ul 类型的节点
  [[Prototype]]: HTMLElement
    constructor: HTMLElement()
    blur: blur()
    click: click()
    focus: focus()
    innerText: ""
    ...
    # HTMLElement 构造函数的原型对象上挂载了很多 HTML 元素自有的属性和方法
    # 结合上图可知,这些属性和方法在 SVG 中是不可用的
    [[Prototype]]: Element
      constructor: Element()
      getElementsByClassName: getElementsByClassName()
      getElementsByTagName: getElementsByTagName()
      querySelector: querySelector()
      querySelectorAll: querySelectorAll()
      ...
      # Element 构造函数的原型对象上也挂载了很多共有的属性和方法,且在 SVG 中也是可用的
      [[Prototype]]: Node
        constructor: Node()
        nodeName: "UL"
        nodeType: 1
        appendChild: appendChild()
        ...
        # Node 类型是最基本的类型,有一些 DOM 节点最基本的共有属性和方法
        [[Prototype]]: EventTarget
          constructor: EventTarget()
          addEventListener: addEventListener()
          dispatchEvent: dispatchEvent()
          removeEventListener: removeEventListener()
          # EventTarget 对象用来处理事件,只挂载了这三个方法
          [[Prototype]]: Object
            constructor: Object()
            hasOwnProperty: hasOwnProperty()
            isPrototypeOf: isPrototypeOf()
            ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

TIP

上面代码打印时使用的是console.dir()方法。

大多数浏览器在其开发者工具中支持两个命令:console.logconsole.dir. 他们将参数输出到控制台。对于 JavaScript 对象,这些命令通常执行相同的操作。但对于 DOM 元素,它们是不同的:

  • console.log()显示 DOM Tree。
  • console.dir()显示为 DOM 对象。

# 参考

上次更新: 5/9/2022, 5:34:36 PM