DOM 节点层次结构

每个 DOM 节点都属于相应的内建类。

层次结构(hierarchy)如下:

![[Pasted image 20240426175513.png]]

命名空间

HTML/XML 文档在浏览器内均被表示为 DOM 树。

HTML 以外其他网页上常见的 XML:

对应的命名空间:

DOM 的很多方法都有相对应的命名空间方法 *NS(namespace, ...) 用来处理非 HTML 的 Element

NodeElement

节点类型

nodeType

nodeType 属性提供了一种“过时的”用来获取 DOM 节点类型的方法。

它有一个数值型值:

一共有 12 种节点类型

nodeNametagName

给定一个 DOM 节点,可以从 nodeName 或者 tagName 属性中读取它的标签名:

document.body.nodeName // BODY
document.body.tagName // BODY

节点内容

innerHTML

innerHTML 属性仅对元素节点有效,其他节点使用 [[#nodeValue/data|nodeValue/data]]

注意:

outerHTML

<div>Hello, world!</div>

<script>
  let div = document.querySelector('div');

  // 使用 <p>...</p> 替换 div.outerHTML
  div.outerHTML = '<p>A new element</p>';

  // 蛤!'div' 还是原来那样!
  // 但是页面 DOM 已经变成了 <p>
  console.log(div.outerHTML); // <div>Hello, world!</div>
</script>

在 div.outerHTML = ... 中发生的事情是:

  1. div 被从文档(document)中移除
  2. 另一个 HTML 片段 <p>A new element</p> 被插入到其位置上
  3. div 仍拥有其旧的值

nodeValue/data

[[#innerHTML|innerHTML]] 属性仅对元素节点有效

文本节点、注释节点,具有它们的对应项:nodeValue 和 data 属性。这两者在实际使用中几乎相同,只有细微规范上的差异。同样,可读可写

元素节点没有 nodeValue 和 data 属性,或者为 null

innerTextouterText

只有元素节点有

innerText

outerText

textContent

所有 Node 都有

特别说明

以上所有属性 document 节点都没有,或者为 null

节点显隐

hidden 特性(attribute)和 DOM 属性(property)指定元素是否可见。

可以在 HTML 中使用它,或者使用 JS 对其进行赋值:

<div>Both divs below are hidden</div>

<div hidden>With the attribute "hidden"</div>

<div id="elem">JavaScript assigned the property "hidden"</div>

<script>
  elem.hidden = true
</script>

从技术上来说,hidden 与 style="display:none" 做的是相同的事。

集合:NodeListHTMLCollection

哪些常见操作会返回这二者?

NodeList

HTMLCollection

NodeList

属性和方法:

forEach 执行流程:

// forEach 执行流程模拟
NodeList.prototype.forEach = function forEach(cb) {
    const len = this.length // 先获取到 length 进行保存,之后及时 length 更新了也不会改变
    for (let i = 0; i < len; i++) { // 就遍历到 len
        if (i in this) { // 当前遍历的元素存在
            cb(this[i], i, this)
        }
    }
}

迭代器执行流程:

// 迭代器执行流程模拟
NodeList.prototype[Symbol.iterator] = function* iterator() {
    for (let i = 0; i < this.length; i++) {
        yield this[i]
    }
}

// 或
NodeList.prototype[Symbol.iterator] = function iterator() {
    let i = -1
    let self = this
    return {
        next: () => {
            i++ // 每次调用 next,游标往下指
            return { value: self[i], done: i === self.length }
        }
    }
}

所以:

HTMLCollection

属性和方法:

版本说明

HTML5 之前基本没有开放 Node 相关的接口,和 NodeNodeList 相关的 API 基本都是 HTML5 新增的(不绝对),如:elem.childNodesquerySelector*