[TOC]

DOM节点类

一、不同的DOM节点可能有不同的属性。
【示例1】标签相对应的元素节点具有链接相关的(link-related)属性,标签相对应的元素节点具有与输入相关的属性,等。
二、文本节点与元素节点不同。所有这些标签对应的DOM节点之间也存在共有的属性和方法,因为所有类型的DOM节点都形成了一个单一层次的结构(single hierarchy)
三、每个DOM节点都属于相应的内建类,这些类形成层次结构(hierarchy)。
四、层次结构的根节点是EventTarget,Node继承自它,其他DOM节点继承自Node
image.png
五、DOM节点是常规的JavaScript对象。它们使用基于原型的类进行继承。
1、类如下所示:
(1)EventTarget
是根的“抽象(abstract)”类。该类的对象从未被创建。它作为一个基础,以便让所有的DOM节点都支持所谓的“事件(event)”。
(2)Node
①也是一个“抽象类”,充当DOM节点的基础。它提供了树的核心功能:parentNode, nextSibling, childNodes等(它们都是getter)。
②Node类的对象从未被创建,但是有一些继承自它的具体的节点类。
【示例1】文本节点的Text,元素节点的Element,以及更多异域(exotic)类,例如注释节点的Comment。
(3)Element
①是DOM元素的基本类。它提供了元素级的导航
【示例1】nextElementSibling, children,以及像getElementsByTagName和querySelector这样的搜索方法。
②浏览器中不仅有HTML,还会有XML和SVG。
③Element类充当更多特定类的基本类:SVGElement, XMLElement和HTMLElement
(4)HTMLElement
①最终是所有HTML元素的基本类。
②各种HTML元素均继承自它

③每个标签都有自己的类,这些类可以提供特定的属性和方法。
六、给定节点的全部属性和方法都是继承的结果

【示例】元素的DOM对象。它属于HTMLInputElement类。它获取属性和方法,并将其作为下列类(按继承顺序列出)的叠加
- HTMLInputElement — 该类提供特定于输入的属性,
- HTMLElement — 它提供了通用(common)的 HTML 元素方法(以及 getter 和 setter)
- Element — 提供通用(generic)元素方法,
- Node — 提供通用 DOM 节点属性,
- EventTarget — 为事件(包括事件本身)提供支持,
- ……最后,它继承自 Object,因为像 hasOwnProperty 这样的“普通对象”方法也是可用的。

七、规范中的IDL
1、在规范中,DOM类不是使用JavaScript来描述的,而是一种特殊的接口描述语言(Interface description language),简写为IDL。
2、在IDL中,所有属性以其类型开头,如,DOMString和boolean等。
3、摘录

// 定义 HTMLInputElement
// 冒号 ":" 表示 HTMLInputElement 继承自 HTMLElement
interface HTMLInputElement: HTMLElement {
  // 接下来是 <input> 元素的属性和方法

  // "DOMString" 表示属性的值是字符串
  attribute DOMString accept;
  attribute DOMString alt;
  attribute DOMString autocomplete;
  attribute DOMString value;

  // 布尔值属性(true/false)
  attribute boolean autofocus;
  ...
  // 现在方法:"void" 表示方法没有返回值
  void select();
  ...
}

查看DOM节点类名

一、查看DOM节点类名的方式有:constructor属性,toString,console.dir
检查继承的方式有:instanceof
二、可以通过回调来查看DOM节点类名,因为对象通常都具有constructor属性。它引用类的constructor,constructor.name就是它的名称



alert(document.body.constructor.name) // HTMLBodyElement

// toString
alert(document.body); // [object HTMLBodyElement]

// instanceof来检查继承
alert( document.body instanceof HTMLBodyElement ); // true
alert( document.body instanceof HTMLElement ); // true
alert( document.body instanceof Element ); // true
alert( document.body instanceof Node ); // true
alert( document.body instanceof EventTarget ); // true

【示例2】document继承自Node还是Element,或者可能是HTMLElement?

// 为了以字符串的形式获取一个类的name,我们可以使用construcor.name
// 对整个document的原型链执行该操作,直到class Node
alert(HTMLDocument.prototype.constructor.name); // HTMLDocument
alert(HTMLDocument.prototype.__proto__.constructor.name); // Document
alert(HTMLDocument.prototype.__proto__.__proto__.constructor.name); // Node

三、在浏览器中,可以使用console.dir(elem)输出元素来查看。在控制台中,可以看到HTMLElement.prototype和Element.prototype等。
1、console.log和console.dir
(1)对于JavaScript对象,这些命令通常做的是相同的事。
(2)对于DOM元素,它们是不同的
①console.log(elem)显示元素的DOM树。
②console.dir(elem)将元素显示为DOM对象,非常适合探索其属性。

DOM节点属性

“nodeType”属性:查看节点类型

一、nodeType属性提供了另一种“过时的”用来获取DOM节点类型的方法
1、它有一个数值型值
(1)对于元素节点 elem.nodeType == 1
(2)对于文本节点 elem.nodeType == 3
(3)对于document对象 elem.nodeType == 9
(4)规范中还有一些其他值
【示例1】

<body>
  <script>
  let elem = document.body;

  // 让我们检查一下它是什么?
  alert(elem.nodeType); // 1 => element

  // 第一个子节点是
  alert(elem.firstChild.nodeType); // 3 => text

  // 对于 document 对象,类型是 9
  alert( document.nodeType ); // 9
  </script>
</body>

二、现代脚本中,我们可以使用instanceof和其他基于类的检查方法来查看节点类型,但有时nodeType可能更简单。
1、我们只能读取nodeType而不能修改它。

nodeName和tagName:元素名,标签名

一、给定一个DOM节点,我们可以从nodeName或者tagName属性中读取它的标签名
【示例1】

alert(document.body.nodeName); // BODY
alert(document.body.tagName); // BODY

二、nodeName, tagName之间的不同
1、nodeName是为任意Node定义的
(1)对于元素,它的意义与tagName相同。
(2)对于其他节点类型(text, conment等),它拥有一个对应节点类型的字符串。
2、tagName属性仅适用于Element节点。
三、tagName仅受元素节点支持(因为它起源于Element类),而nodeName则可以说明其他节点类型。
【示例1】比较一下document的tagName和nodeName,以及一个注释节点

<body><!-- comment -->

  <script>
    // for comment
    alert( document.body.firstChild.tagName ); // undefined(不是一个元素)
    alert( document.body.firstChild.nodeName ); // #comment

    // for document
    alert( document.tagName ); // undefined(不是一个元素)
    alert( document.nodeName ); // #document
  </script>
</body>

1、如果我们只处理元素,那么tagName和nodeName这两种方法,我们都可以使用,没有区别。
四、浏览器有两种处理文档(document)的模式:HTML和XML。
1、通常,HTML模式用于网页。
(1)在HTML模式下,tagName/nodeName始终是大写的:它是BODY,而不是或
2、只有在浏览器接收到带有header Content-Type: application/xml+xhtml的XML-document时,XML模式才会被启用。
(2)在XML模式下,大小写保持为“原样”。(20210308):如今,XML模式很少被使用。

innerHTML:元素的HTML内容

一、innerHTML属性允许将元素中的HTML获取为字符串形式。
二、innerHTML是更改页面最有效的方式之一。
【示例1】以下示例显示了document.body中的内容,然后将其完全替换

<body>
  <p>A paragraph</p>
  <div>A div</div>

  <script>
    alert( document.body.innerHTML ); // 读取当前内容
    document.body.innerHTML = 'The new BODY!'; // 替换它
  </script>

</body>

【示例2】我们可以尝试插入无效的HTML,浏览器胡修复我们的错误

<body>

  <script>
    document.body.innerHTML = '<b>test'; // 忘记闭合标签
    alert( document.body.innerHTML ); // <b>test</b>(被修复了)
  </script>

</body>

三、如果innerHTML将一个