DOM

现行标准 — 最后更新

参与:
GitHub whatwg/dom (新问题, 开放的问题)
在 Matrix 上聊天
提交:
GitHub whatwg/dom/commits
此提交的快照
@thedomstandard
测试:
web-platform-tests dom/ (进行中的工作)
翻译 (非规范性)
日本語
简体中文
한국어

摘要

DOM 定义了一个平台中立的模型,用于事件、活动中止和节点树。

1. 基础设施

本规范依赖于现行标准的基础设施标准。[INFRA]

本规范中使用的一些术语在编码选择器受信任类型Web IDLXMLXML中的命名空间中有定义。 [ENCODING] [SELECTORS4] [TRUSTED-TYPES] [WEBIDL] [XML] [XML-NAMES]

当需要扩展时,可以相应地更新 DOM 标准,或者可以编写一个新标准,该标准可以利用为 适用的规范 提供的可扩展性钩子。

1.1.

是一个有限的层次树结构。树的顺序是对的先序、深度优先遍历。

参与的对象有一个父节点,它要么是 null,要么是一个对象,并且有子节点,它是一个对象的有序集合。对象A父节点是对象B,则AB子节点

对象的是它自己,如果它的为null,否则它的根是它的的根。的根是参与该的任意对象,而该对象的为null。

如果对象A是对象B,或者对象A是对象C,而CB后代,则对象A被称为对象B后代

包含后代是指一个对象或其后代之一。

当且仅当BA后代时,称对象A为对象B祖先

包含祖先是指一个对象或其祖先之一。

当且仅当BA共享相同的非空父节点时,称对象A为对象B同胞

包含同胞是指一个对象或其同胞之一。

如果AB在同一个中,并且A树的顺序中位于B之前,则称对象A先于对象B

如果AB在同一个中,并且A树的顺序中位于B之后,则称对象A继于对象B

一个对象的第一个子节点是其第一个子节点,如果它没有子节点,则为 null。

一个对象的最后一个子节点是其最后一个子节点,如果它没有子节点,则为 null。

一个对象的前一个同胞是指其第一个先于同胞,如果没有,则为 null。

一个对象的下一个同胞是指其第一个继于同胞,如果没有,则为 null。

一个对象的索引是其先于同胞的数量,如果没有,则为 0。

1.2. 有序集合

有序集合解析器接受一个字符串input,然后执行以下步骤:

  1. inputTokens在 ASCII 空白字符处分割input的结果。

  2. tokens为一个新的有序集合

  3. 对于 inputTokens 中的每个 token: 将 token 追加tokens

  4. 返回tokens

有序集合序列化器接受一个set,并返回使用U+0020 SPACE连接的set串联结果

1.3. 选择器

给定字符串 selectors节点 node作用域匹配选择器字符串 的步骤如下:

  1. selector解析选择器 selectors 的结果。 [SELECTORS4]

  2. 如果 selector 返回失败,则 抛出一个 "SyntaxError"DOMException

  3. 返回 selectornode根节点 通过 作用域根 node 进行 在树中匹配选择器 的结果。[SELECTORS4]

不打算支持在选择器中使用命名空间,也不会添加此功能。

1.4. 名称验证

当一个字符串满足以下条件时,称为有效的命名空间前缀:其长度至少为1,并且不包含ASCII 空白符、U+0000 NULL、U+002F (/) 或 U+003E (>)。

当一个字符串满足以下条件时,称为有效的属性本地名:其长度至少为1,并且不包含ASCII 空白符、U+0000 NULL、U+002F (/)、U+003D (=) 或 U+003E (>)。

当一个字符串name满足下列步骤返回 true 时,称为有效的元素本地名

  1. 如果name长度为0,则返回 false。

  2. 如果name的第0个码点ASCII 字母

    1. 如果name包含ASCII 空白符、U+0000 NULL、U+002F (/) 或 U+003E (>),则返回 false。

    2. 返回 true。

  3. 如果name的第0个码点不是 U+003A (:)、U+005F (_),也不在 U+0080~U+10FFFF 范围内,则返回 false。

  4. 如果name的后续码点(如有)不是ASCII 字母ASCII 数字、U+002D (-)、U+002E (.)、U+003A (:)、U+005F (_),或者不在 U+0080~U+10FFFF 范围内,则返回 false。

  5. 返回 true。

此概念用于在通过 DOM API 构建时验证元素本地名称。其意图是允许任何可以使用 HTML 解析器构造的名称(第一个码点ASCII 字母的分支),以及一些额外的可能性。对于那些额外的可能性,出于历史原因,ASCII 范围受到限制,但超出 ASCII 的任何内容都是允许的。

以下与 JavaScript 兼容的正则表达式是有效元素本地名称的实现:

/^(?:[A-Za-z][^\0\t\n\f\r\u0020/>]*|[:_\u0080-\u{10FFFF}][A-Za-z0-9-.:_\u0080-\u{10FFFF}]*)$/u
        

一个字符串,如果它不包含ASCII 空白字符、 U+0000 NULL 或 U+003E (>),则它是一个有效的文档类型名称

空字符串是一个有效的文档类型名称

验证并提取一个 namespacequalifiedName,给定一个 context

  1. 如果 namespace 是空字符串,则将其设置为 null。

  2. prefix 设置为 null。

  3. localName 设置为 qualifiedName

  4. 如果 qualifiedName 包含 U+003A (:):

    1. splitResult 设置为运行 严格拆分的结果,参数为 qualifiedName 和 U+003A (:)。

    2. prefix 设置为 splitResult[0]。

    3. localName 设置为 splitResult[1]。

    4. 如果 prefix 不是一个 有效的命名空间前缀,则 抛出一个 "InvalidCharacterError" DOMException

  5. 断言prefix 要么为 null,要么是一个 有效的命名空间前缀

  6. 如果 context 是 "attribute" 并且 localName 不是 有效的属性本地名称,则 抛出一个 "InvalidCharacterError" DOMException

  7. 如果 context 是 "element" 并且 localName 不是 有效的元素本地名称,则 抛出一个 "InvalidCharacterError" DOMException

  8. 如果 prefix 不为 null 且 namespace 为 null,则 抛出一个 "NamespaceError" DOMException

  9. 如果 prefix 是 "xml" 且 namespace 不是 XML 命名空间,则 抛出一个 "NamespaceError" DOMException

  10. 如果 qualifiedNameprefix 是 "xmlns" 并且 namespace 不是 XMLNS 命名空间,则 抛出一个 "NamespaceError" DOMException

  11. 如果 namespaceXMLNS 命名空间 并且 qualifiedNameprefix 均不是 "xmlns",则 抛出一个 "NamespaceError" DOMException

  12. 返回 (namespace, prefix, localName)。

本规范中的各种 API 过去对命名空间前缀、属性本地名称、元素本地名称和文档类型名称的验证更为严格。这样做的方式与各种 XML 相关规范保持一致。(尽管并非所有这些规范中的规则都被强制执行。)

这被发现对 Web 开发人员来说很烦人,特别是因为这意味着有些名称可以通过 HTML 解析器创建,但不能通过 DOM API 创建。因此,验证已放宽到仅限于上述描述的那些。

2. 事件

2.1. “DOM 事件”简介

在整个 Web 平台中,事件派发到对象,以标识发生的事件,例如网络活动或用户交互。这些对象实现了EventTarget接口,因此可以通过调用addEventListener()来添加事件监听器以观察事件

obj.addEventListener("load", imgFetched)

function imgFetched(ev) {
  // great success}

事件监听器可以通过使用removeEventListener()方法删除,传递相同的参数。

或者,也可以通过将AbortSignal传递给addEventListener(),然后调用控制器上持有信号的abort()来删除事件监听器

事件也是对象,并实现了Event接口(或派生接口)。在上面的例子中,ev事件ev作为参数传递给事件监听器回调(通常是如上所示的JavaScript函数)。事件监听器通过事件type属性值(上例中的"load")来区分事件。事件target属性值返回事件派发到的对象(如上例中的obj)。

虽然事件通常由用户代理在用户交互或某些任务完成时派发,但应用程序可以通过使用通常称为合成事件的方式派发事件

// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) })

// create and dispatch the event
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}})
obj.dispatchEvent(event)

除了用于传递信号外,事件有时也用于让应用程序控制操作中的后续步骤。例如,作为表单提交的一部分,type属性值为"submit"的事件派发。如果调用了该事件preventDefault()方法,则表单提交将被终止。希望通过应用程序事件(合成事件)派发该功能的应用程序,可以使用dispatchEvent()方法的返回值。

if(obj.dispatchEvent(event)) {
  // event was not canceled, time for some magic}

当一个事件派发到一个参与(例如,一个元素)的对象时,它也可以到达该对象的祖先上的事件监听器。实际上,该对象的所有包含祖先捕获为true的事件监听器都将按照树的顺序被调用。然后,如果事件bubbles为true,则该对象的所有包含祖先捕获为false的事件监听器将按照相反的树的顺序被调用。

让我们看一个事件中如何工作的例子:

<!doctype html>
<html>
 <head>
  <title>Boring example</title>
 </head>
 <body>
  <p>Hello <span id=x>world</span>!</p>
  <script>
   function test(e) {
     debug(e.target, e.currentTarget, e.eventPhase)
   }
   document.addEventListener("hey", test, {capture: true})
   document.body.addEventListener("hey", test)
   var ev = new Event("hey", {bubbles:true})
   document.getElementById("x").dispatchEvent(ev)
  </script>
 </body>
</html>

debug函数将被调用两次。每次事件target属性值将是span元素。第一次currentTarget属性值将是document,第二次将是body元素eventPhase属性值将从CAPTURING_PHASE切换到BUBBLING_PHASE。如果为span元素注册了一个事件监听器eventPhase属性值将是AT_TARGET

2.2. 接口 Event

[Exposed=*]
interface Event {
  constructor(DOMString type, optional EventInit eventInitDict = {});

  readonly attribute DOMString type;
  readonly attribute EventTarget? target;
  readonly attribute EventTarget? srcElement; // legacy
  readonly attribute EventTarget? currentTarget;
  sequence<EventTarget> composedPath();

  const unsigned short NONE = 0;
  const unsigned short CAPTURING_PHASE = 1;
  const unsigned short AT_TARGET = 2;
  const unsigned short BUBBLING_PHASE = 3;
  readonly attribute unsigned short eventPhase;

  undefined stopPropagation();
           attribute boolean cancelBubble; // legacy alias of .stopPropagation()
  undefined stopImmediatePropagation();

  readonly attribute boolean bubbles;
  readonly attribute boolean cancelable;
           attribute boolean returnValue;  // legacy
  undefined preventDefault();
  readonly attribute boolean defaultPrevented;
  readonly attribute boolean composed;

  [LegacyUnforgeable] readonly attribute boolean isTrusted;
  readonly attribute DOMHighResTimeStamp timeStamp;

  undefined initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false); // legacy
};

dictionary EventInit {
  boolean bubbles = false;
  boolean cancelable = false;
  boolean composed = false;
};

一个Event对象通常被称为一个事件。它用于标识某些事情已经发生,例如,一个图像已经完成下载。

一个潜在事件目标是 null 或一个EventTarget对象。

一个事件有一个关联的目标(一个潜在事件目标)。除非另有说明,否则它为 null。

一个事件有一个关联的相关目标(一个潜在事件目标)。除非另有说明,否则它为 null。

其他规范使用相关目标来定义一个relatedTarget属性。[UIEVENTS]

一个事件有一个关联的触摸目标列表(一个列表,包含零个或多个潜在事件目标)。除非另有说明,否则它为空列表。

触摸目标列表专门用于定义TouchEvent接口和相关接口。[TOUCH-EVENTS]

一个事件有一个关联的路径。一个路径是一个列表,包含结构体。每个结构体由一个调用目标(一个EventTarget对象)、一个在 shadow 树中的调用目标(一个布尔值)、一个shadow 调整后的目标(一个潜在事件目标)、一个相关目标(一个潜在事件目标)、一个触摸目标列表(一个列表,包含潜在事件目标)、一个关闭树的根(一个布尔值)和一个关闭树中的插槽(一个布尔值)。一个路径最初为空列表。

event = new Event(type [, eventInitDict])
返回一个新的event,其type属性值设置为typeeventInitDict参数允许通过同名对象成员设置bubblescancelable属性。
event . type
返回event的类型,例如"click"、"hashchange"或"submit"。
event . target
返回event分派的对象(其目标)。
event . currentTarget
返回当前正在调用其事件侦听器回调函数的对象。
event . composedPath()
返回event调用目标对象(将在其上调用侦听器的对象),但不包括任何节点,这些节点在shadow 树中,其shadow root模式为"closed"且无法从eventcurrentTarget到达。
event . eventPhase
返回事件的阶段,它是以下之一:NONECAPTURING_PHASEAT_TARGETBUBBLING_PHASE
event . stopPropagation()
当在中分派时,调用此方法会阻止event到达当前对象以外的任何对象。
event . stopImmediatePropagation()
调用此方法会阻止event在当前侦听器运行结束后到达任何注册的事件侦听器,并且当在中分派时,也会阻止event到达任何其他对象。
event . bubbles
根据event的初始化方式返回 true 或 false。如果event通过其目标祖先按相反的树顺序传播,则为 true;否则为 false。
event . cancelable
根据event的初始化方式返回 true 或 false。其返回值并不总是有意义,但 true 可以表示在分派event的过程中,部分操作可以通过调用preventDefault()方法来取消。
event . preventDefault()
如果在cancelable属性值为 true 时调用,并且在执行带有passive设置为 false 的侦听器时,通知导致分派event的操作需要取消。
event . defaultPrevented
如果成功调用preventDefault()表示取消,则返回 true;否则返回 false。
event . composed
根据event的初始化情况返回 true 或 false。如果event调用了超过作为其目标ShadowRoot节点的监听器,则返回 true;否则返回 false。
event . isTrusted
如果event由用户代理分派,则返回 true,否则返回 false。
event . timeStamp
以毫秒为单位返回event的时间戳,相对于发生时间。

type属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为空字符串。

target获取步骤是返回this目标

srcElement获取步骤是返回this目标

currentTarget属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为 null。

composedPath()方法的步骤为:

  1. composedPath成为一个空的列表

  2. path成为this路径

  3. 如果path为空,则返回composedPath

  4. currentTarget成为thiscurrentTarget属性值。

  5. 断言currentTarget 是一个 EventTarget 对象。

  6. 追加currentTargetcomposedPath

  7. currentTargetIndex设为 0。

  8. currentTargetHiddenSubtreeLevel设为 0。

  9. index设为path大小 - 1。

  10. index大于或等于 0 时:

    1. 如果path[index]的关闭树的根为 true,则将currentTargetHiddenSubtreeLevel增加 1。

    2. 如果path[index]的调用目标currentTarget,则将currentTargetIndex设置为index,并中断

    3. 如果path[index]的关闭树中的插槽为 true,则将currentTargetHiddenSubtreeLevel减少 1。

    4. 减少index的值 1。

  11. currentHiddenLevelmaxHiddenLevel设为currentTargetHiddenSubtreeLevel

  12. index设为currentTargetIndex - 1。

  13. index大于或等于 0 时:

    1. 如果path[index]的关闭树的根为 true,则将currentHiddenLevel增加 1。

    2. 如果currentHiddenLevel小于或等于maxHiddenLevel,则前置path[index]的调用目标composedPath

    3. 如果 path[index] 的 slot-in-closed-tree 为 true:

      1. currentHiddenLevel减少 1。

      2. 如果currentHiddenLevel小于maxHiddenLevel,则将maxHiddenLevel设为currentHiddenLevel

    4. 减少index的值 1。

  14. currentHiddenLevelmaxHiddenLevel设为currentTargetHiddenSubtreeLevel

  15. index设为currentTargetIndex + 1。

  16. index小于path大小时:

    1. 如果path[index]的关闭树中的插槽为 true,则将currentHiddenLevel增加 1。

    2. 如果currentHiddenLevel小于或等于maxHiddenLevel,则追加path[index]的调用目标composedPath

    3. 如果 path[index] 的 root-of-closed-tree 为 true:

      1. currentHiddenLevel减少 1。

      2. 如果currentHiddenLevel小于maxHiddenLevel,则将maxHiddenLevel设为currentHiddenLevel

    4. 增加index的值 1。

  17. 返回composedPath

eventPhase属性必须返回初始化时的值,该值必须是以下之一:

NONE(数值 0)
事件当前未被分派时处于此阶段。
CAPTURING_PHASE(数值 1)
当一个事件分派到一个参与的对象时,它将在到达其目标之前处于此阶段。
AT_TARGET(数值 2)
当一个事件分派时,它将在其目标上处于此阶段。
BUBBLING_PHASE(数值 3)
当一个事件分派到一个参与的对象时,它将在到达其目标后处于此阶段。

最初该属性必须初始化为NONE


每个事件都具有以下关联标志,最初都未设置:

stopPropagation()方法的步骤是设置this停止传播标志

cancelBubble获取步骤是如果this停止传播标志已设置,则返回 true;否则返回 false。

cancelBubble设置步骤是如果给定值为 true,则设置this停止传播标志;否则不执行任何操作。

stopImmediatePropagation()方法的步骤是设置this停止传播标志this立即停止传播标志

bubblescancelable属性必须返回初始化时的值。

设置取消标志,给定一个事件event,如果eventcancelable属性值为 true 并且event在被动侦听器中的标志未设置,则设置event取消标志,否则不执行任何操作。

returnValue获取步骤是如果this取消标志已设置,则返回 false;否则返回 true。

returnValue设置步骤是如果给定值为 false,则设置取消标志,并将this作为参数;否则不执行任何操作。

preventDefault()方法的步骤是将取消标志设置为this

在某些情况下,调用preventDefault()无效。建议用户代理在开发者控制台中记录具体原因,以帮助调试。

defaultPrevented获取步骤是如果this取消标志已设置,则返回 true;否则返回 false。

composed获取步骤是如果this合成标志已设置,则返回 true;否则返回 false。


isTrusted属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为 false。

isTrusted是一个方便的属性,指示一个事件是否由用户代理分派(而不是使用dispatchEvent())。唯一的传统例外是click(),它导致用户代理分派一个isTrusted属性初始化为 false 的事件

timeStamp属性必须返回初始化时的值。


初始化一个event,使用typebubblescancelable,运行以下步骤:

  1. 设置event初始化标志

  2. 取消设置event停止传播标志立即停止传播标志取消标志

  3. 设置eventisTrusted属性为 false。

  4. 设置event目标为 null。

  5. eventtype属性设置为type

  6. eventbubbles属性设置为bubbles

  7. eventcancelable属性设置为cancelable

initEvent(type, bubbles, cancelable)方法的步骤为:

  1. 如果this分派标志已设置,则返回。

  2. 初始化this,使用typebubblescancelable

initEvent()事件构造函数是多余的,并且无法设置composed。它必须为了遗留内容而支持。

2.3. Window 接口的传统扩展

partial interface Window {
  [Replaceable] readonly attribute (Event or undefined) event; // legacy
};

每个 Window 对象都有一个关联的 当前事件(未定义或一个 Event 对象)。除非另有说明,否则它是未定义的。

event 的 getter 步骤是返回 this当前事件

强烈建议 Web 开发者依赖传递给事件监听器的 Event 对象,因为这将产生更具可移植性的代码。此属性在 workers 或 worklets 中不可用,并且对于在 shadow trees 中分派的事件是不准确的。

2.4. 接口 CustomEvent

[Exposed=*]
interface CustomEvent : Event {
  constructor(DOMString type, optional CustomEventInit eventInitDict = {});

  readonly attribute any detail;

  undefined initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); // legacy
};

dictionary CustomEventInit : EventInit {
  any detail = null;
};

事件 使用 CustomEvent 接口可以用于携带自定义数据。

event = new CustomEvent(type [, eventInitDict])
其工作方式类似于 Event 的构造函数,但 eventInitDict 参数现在还允许设置 detail 属性。
event . detail
返回创建 event 时的任何自定义数据。 通常用于合成事件。

detail 属性必须返回它初始化时的值。

initCustomEvent(type, bubbles, cancelable, detail) 方法的步骤如下:

  1. 如果 thisdispatch flag 已设置,则返回。

  2. 初始化 this ,包括 typebubblescancelable

  3. thisdetail 属性设置为 detail

2.5. 构造事件

规范可能会为所有或某些事件定义事件构造步骤。该算法接收一个事件event和一个EventIniteventInitDict,如内部事件创建步骤中所示。

这个构造方式可用于Event子类,它们具有比简单的初始化字典成员和IDL属性之间一对一映射更复杂的结构。

构造函数Event接口,或继承自Event接口的接口被调用时,必须运行以下步骤,给定参数typeeventInitDict

  1. 运行内部事件创建步骤,以获得event,使用此接口、null、当前时间和eventInitDict

  2. eventtype属性初始化为type

  3. 返回event

要使用eventInterface 创建事件,该接口必须是Event或继承自它的接口,并且可选地提供realm realm,运行以下步骤:

  1. 如果未提供realm,则将其设置为null。

  2. dictionary设置为将JavaScript值undefined转换为eventInterface构造函数所接受的字典类型的结果。(此字典类型将是EventInit或继承自它的字典类型。)

    如果需要成员,这种方法不起作用;请参见whatwg/dom#600

  3. 运行内部事件创建步骤,以eventInterfacerealm、该事件信号发生的时间和dictionary为参数,得到event

    在macOS中,输入操作的发生时间可以通过NSEvent对象的timestamp属性获得。

  4. eventisTrusted属性初始化为true。

  5. 返回event

创建事件用于需要分别创建分发事件的其他规范,而不是简单地触发事件。它确保事件的属性初始化为正确的默认值。

内部事件创建步骤,给定eventInterfacerealmtimedictionary,如下所示:

  1. 使用eventInterface创建一个新对象作为event的结果。如果realm非空,则使用该realm;否则,使用Web IDL中定义的默认行为。

    截至本文撰写时,Web IDL 尚未定义任何默认行为;请参见whatwg/webidl#135

  2. 设置event初始化标志

  3. eventtimeStamp属性初始化为给定timeevent相关全局对象相对高分辨率粗略时间

  4. 对于 dictionary 中的每个 membervalue: 如果 event 具有 标识符member 的属性,则将该属性初始化为 value

  5. 运行事件构造步骤,参数为eventdictionary

  6. 返回event

2.6. 定义事件接口

通常,在定义一个继承自Event的新接口时,请务必征求WHATWGW3C WebApps WG社区的反馈。

CustomEvent接口可以作为起点。然而,不要引入任何init*Event()方法,因为它们与构造函数是冗余的。继承自Event接口的接口中如果包含此类方法,也只是出于历史原因。

2.7. 接口 EventTarget

[Exposed=*]
interface EventTarget {
  constructor();

  undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
  undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  undefined handleEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive;
  boolean once = false;
  AbortSignal signal;
};

一个 EventTarget 对象表示一个目标,当某些事情发生时,一个事件可以被派发到该目标。

每个 EventTarget 对象都有一个相关的事件监听器列表(一个由零个或多个事件监听器组成的列表)。它最初是空的列表。

一个事件监听器 可以用于观察特定的事件,它由以下部分组成:

虽然回调是一个 EventListener 对象,事件监听器 是一个更广泛的概念,如上所述。

每个 EventTarget 对象还有一个相关的获取父级算法, 该算法接收一个事件 event,并返回一个EventTarget 对象。除非另有说明,它返回null。

节点影子根节点文档会重写 获取父级算法。

每个 EventTarget 对象可以有一个相关的激活行为算法。该激活行为算法接收一个事件,如 派发 算法中所示。

这是因为用户代理在某些EventTarget 对象上执行某些操作,例如 area 元素,以响应其MouseEventtype 属性为click的合成事件。由于Web兼容性问题,它未能被移除,并且现在成为定义激活某些内容的固定方式。[HTML]

每个 EventTarget 对象如果具有激活行为,还可以同时(而非单独)具有遗留预激活行为算法 和遗留取消激活行为 算法。

这些算法仅存在于复选框和单选框的 input 元素中, 不适用于其他任何内容。[HTML]

target = new EventTarget();

创建一个新的EventTarget 对象,开发者可以使用它来派发并 监听事件

target . addEventListener(type, callback [, options])

type属性值为type事件附加一个事件侦听器callback参数设置将在事件分派时调用的回调函数

options为true时,监听器在捕获阶段触发;当为false或未设置时,监听器在冒泡阶段触发。无论设置如何,若事件处于目标阶段,监听器均会被触发。

options设置为true时,表示监听器为被动模式,不会调用preventDefault()来取消事件。

options设置为true时,表示监听器仅触发一次,触发后将被移除。

若为options指定了AbortSignal,当信号被中止时,监听器将被移除。

若已存在相同typecallbackcapture的事件监听器,则不会再次添加。

target . removeEventListener(type, callback [, options])

移除target中与typecallbackoptions匹配的事件监听器。

target . dispatchEvent(event)

派发event事件,并返回true,若事件的cancelable属性为false或未调用preventDefault(),否则返回false。

展开 options,请执行以下步骤:

  1. 如果options是布尔值,则返回options

  2. 返回options["capture"]。

进一步展开 options,请执行以下步骤:

  1. captureoptions展开的结果。

  2. once为false。

  3. passivesignal为null。

  4. 如果options是一个字典,则:

    1. once设置为options["once"]。

    2. 如果options["passive"] 存在,则将passive设置为options["passive"]。

    3. 如果options["signal"] 存在,则将signal设置为options["signal"]。

  5. 返回capturepassiveoncesignal

new EventTarget()构造函数步骤不执行任何操作。

由于其他地方声明的默认值,返回的EventTarget获取父级算法将返回null,并且它没有激活行为遗留预激活行为, 或遗留取消激活行为

将来我们可能会允许自定义获取父级算法。请告诉我们 这对您的程序是否有用。目前,所有作者创建的EventTarget 不参与树结构。

默认被动值,给定一个事件类型type和一个EventTarget eventTarget,由下列步骤决定:

  1. 若下列条件全部满足,则返回true:

  2. 返回false。

添加事件监听器,给定一个EventTarget 对象eventTarget和一个事件监听器listener,请执行以下步骤:

  1. eventTarget是一个ServiceWorkerGlobalScope 对象,其service worker脚本资源曾经评估过的标志被设置,且listener类型与任何service worker 事件类型属性值匹配,则向控制台报告一个警告,提示这可能不会产生预期结果。[SERVICE-WORKERS]

  2. 如果 listenersignal 不为 null 并且已中止,则返回。

  3. listener回调为null,则返回。

  4. listener被动为null,则将其设置为listener默认被动值,根据listener类型eventTarget

  5. eventTarget事件监听器列表包含一个事件监听器,其类型listener类型回调listener回调,且捕获listener捕获,则追加 listenereventTarget事件监听器列表中。

  6. listener信号不为null,则添加以下中止步骤:

    1. 移除事件监听器,使用eventTargetlistener

添加事件监听器的概念是为了确保事件处理器使用相同的代码路径。[HTML]

addEventListener(type, callback, options) 方法步骤为:

  1. capturepassiveoncesignal进一步展开 options的结果。

  2. 添加事件监听器,使用this和一个事件监听器,其类型type回调callback捕获capture被动passive一次性once信号signal

移除事件监听器,给定一个EventTarget 对象eventTarget和一个事件监听器 listener,请执行以下步骤:

  1. 如果eventTargetServiceWorkerGlobalScope对象,并且它的Service Worker要处理的事件类型集合包含listener类型,那么报告一个警告到控制台,表明这可能不会产生预期的结果。[SERVICE-WORKERS]

  2. listenerremoved设置为true,并且eventTarget事件侦听器列表中移除listener

HTML 需要这个来定义事件处理器。[HTML]

移除所有事件监听器,给定一个EventTarget 对象eventTarget: 对其每个 listener事件监听器列表项: 移除事件监听器,使用eventTargetlistener

HTML 需要这个来定义document.open()[HTML]

removeEventListener(type, callback, options) 方法步骤为:

  1. capture展开options的结果。

  2. 如果this事件 监听器列表 包含一个事件监听器, 其类型type回调callback,且捕获capture,则移除事件监听器,使用this和该事件监听器

事件侦听器列表不会包含具有相同typecallbackcapture的多个事件侦听器,因为添加事件侦听器会防止这种情况发生。

dispatchEvent(event)方法步骤为:

  1. event派发标志已设置,或其初始化标志未设置,则抛出一个“InvalidStateErrorDOMException

  2. eventisTrusted属性初始化为false。

  3. 返回派发 eventthis的结果。

2.8. 观察事件监听器

一般来说,开发者不会期望事件监听器的存在是可观察的。 事件监听器的影响由其回调决定。也就是说, 开发者添加一个无操作的事件监听器时不会期望它有任何副作用。

不幸的是,一些事件API的设计使得要高效实现它们就需要观察事件侦听器。这使得侦听器的存在是可观察的,即使是空的侦听器也可能对应用程序的行为产生显著的性能影响。例如,可以用于阻止异步滚动的触摸和滚轮事件。在某些情况下,可以通过仅在存在至少一个非被动侦听器时将事件指定为可取消来缓解这一问题。例如,非被动触摸事件侦听器必须阻止滚动,但如果所有侦听器都是被动的,则可以通过使触摸事件不可取消(从而忽略对preventDefault()的调用)来允许滚动并行开始。因此,分派事件的代码能够观察到非被动侦听器的缺失,并使用该信息来清除正在分派的事件的可取消属性。

理想情况下,任何新的事件API都应定义为不需要此属性。(请使用whatwg/dom进行讨论。)

获取遗留的Service Worker获取事件侦听器回调,给定一个ServiceWorkerGlobalScopeglobal,请运行以下步骤。这些步骤将返回一个EventListener对象的列表

  1. callbacks 为 « »。

  2. 对于每一个 listener 属于 global事件监听器列表:如果 listener类型为 "fetch" 并且 listener回调 不为 null, 则 listener回调添加到 callbacks

  3. 返回 callbacks

2.9. 分发事件

要将一个事件分发给一个目标,可选带有legacy target override flaglegacyOutputDidListenersThrowFlag,请按以下步骤操作:

  1. 设置event分发标志

  2. 如果未给出legacy target override flag,则将targetOverride设置为目标,否则设置为目标关联的文档[HTML]

    legacy target override flag仅由HTML使用,且仅当目标是一个窗口对象时使用。

  3. activationTarget设置为null。

  4. relatedTarget设置为针对目标重新定位eventrelatedTarget的结果。

  5. clearTargets 为 false。

  6. 如果 target 不是 relatedTarget 或者 targeteventrelatedTarget

    1. touchTargets设置为一个新的列表

    2. 对于每个touchTarget,它在event触摸目标列表中: 追加针对目标重新定位touchTarget的结果到touchTargets中。

    3. 通过event目标targetOverriderelatedTargettouchTargets,并设置为false,附加到事件路径

    4. 如果event是一个鼠标事件对象,且event类型属性为"click",则isActivationEvent为true;否则为false。

    5. 如果isActivationEvent为true且目标具有激活行为,则将activationTarget设置为目标

    6. 如果目标是一个slottable且已分配,则将slottable设置为目标,否则为null。

    7. slot-in-closed-tree设置为false。

    8. parent设置为调用目标获取父项结果的event

    9. parent非空时:

      1. 如果slottable非空:

        1. 断言:parent是一个插槽

        2. slottable设置为null。

        3. 如果parent是一个影子根,且它的模式是"closed",则将slot-in-closed-tree设置为true。

      2. 如果parent是一个slottable且已分配,则将slottable设置为parent

      3. relatedTarget设置为针对parent重新定位eventrelatedTarget的结果。

      4. touchTargets设置为一个新的列表

      5. 对于每个touchTarget ,它在event触摸目标列表中: 追加针对parent重新定位touchTarget的结果到touchTargets中。

      6. 如果parent是一个窗口对象,或parent是一个节点目标parent包括影子在内的包容性祖先,则:

        1. 如果isActivationEvent为true,event冒泡属性为true,activationTarget为null,且parent具有激活行为,则将activationTarget设置为parent

        2. 附加到事件路径通过eventparent、null、relatedTargettouchTargets,并设置slot-in-closed-tree

      7. 否则,如果parentrelatedTarget,则将parent设置为null。

      8. 否则:

        1. 目标设置为parent

        2. 如果isActivationEvent为true,activationTarget为null,且目标具有激活行为,则将activationTarget设置为目标

        3. 附加到事件路径通过eventparent目标relatedTargettouchTargets,并设置slot-in-closed-tree

      9. 如果parent非空,则将parent设置为调用parent获取父项结果的event

      10. slot-in-closed-tree设置为false。

    10. clearTargetsStruct设置为event路径中的最后一个结构,其影子调整目标非空。

    11. 如果 clearTargetsStructshadow-adjusted targetclearTargetsStructrelatedTarget,或 clearTargetsStructtouch target list 中的 EventTarget 对象是一个节点,其是一个影子根:则将 clearTargets 设置为 true。

    12. 如果activationTarget非空且activationTarget具有旧式预激活行为,则运行activationTarget旧式预激活行为

    13. 对于 eventpath 中的每个 struct,按相反顺序:

      1. 如果struct影子调整目标非空,则 将event事件阶段属性设置为AT_TARGET

      2. 否则,将event事件阶段属性设置为CAPTURING_PHASE

      3. 调用通过structevent、"捕获",以及如果给出的话legacyOutputDidListenersThrowFlag

    14. 对于 eventpath 中的每个 struct

      1. 如果struct影子调整目标非空,则 将event事件阶段属性设置为AT_TARGET

      2. 否则:

        1. 如果event冒泡属性为false,则继续

        2. event事件阶段属性设置为BUBBLING_PHASE

      3. 调用通过structevent、"冒泡",以及如果给出的话legacyOutputDidListenersThrowFlag

  7. event事件阶段属性设置为NONE

  8. event当前目标属性设置为null。

  9. event路径设置为空列表。

  10. 取消设置event分发标志停止传播标志,以及立即停止传播标志

  11. 如果 clearTargets 为 true:

    1. event目标设置为null。

    2. eventrelatedTarget设置为null。

    3. event触摸目标列表设置为空列表。

  12. 如果activationTarget非空:

    1. 如果event取消标志未设置,则使用event运行activationTarget激活行为

    2. 否则,如果activationTarget具有旧式取消激活行为,则运行activationTarget旧式取消激活行为

  13. 如果event取消标志已设置,则返回false;否则返回true。

附加到事件路径,给定一个eventinvocationTargetshadowAdjustedTargetrelatedTargettouchTargets,以及slot-in-closed-tree,请运行这些步骤:

  1. invocationTargetInShadowTree设置为false。

  2. 如果invocationTarget是一个节点,且其是一个影子根,则将invocationTargetInShadowTree设置为true。

  3. root-of-closed-tree设置为false。

  4. 如果invocationTarget是一个影子根,且其模式是"closed",则将root-of-closed-tree设置为true。

  5. 追加一个新的结构event路径,其调用目标invocationTarget调用目标在影子树中invocationTargetInShadowTree影子调整目标shadowAdjustedTargetrelatedTargetrelatedTarget触摸目标列表touchTargets关闭树的根root-of-closed-tree,以及slot-in-closed-treeslot-in-closed-tree

调用,给定一个structevent阶段,以及可选的legacyOutputDidListenersThrowFlag,请运行这些步骤:

  1. event目标设置为event路径中的最后一个结构,其影子调整目标非空,且为structstruct之前的结构。

  2. eventrelatedTarget设置为structrelatedTarget

  3. event触摸目标列表设置为struct触摸目标列表

  4. 如果event停止传播标志已设置,则返回。

  5. 初始化event当前目标属性为struct调用目标

  6. listeners设置为event当前目标属性值的事件侦听器列表克隆

    这避免了在此点之后添加的事件侦听器被运行。请注意,由于已删除字段,移除仍然有影响。

  7. invocationTargetInShadowTree设置为struct调用目标在影子树中

  8. found设置为运行内部调用通过eventlisteners阶段invocationTargetInShadowTree,以及如果给出的话legacyOutputDidListenersThrowFlag的结果。

  9. 如果 found 为 false 且 eventisTrusted 属性为 true:

    1. originalEventType设置为event类型属性值。

    2. 如果event类型属性值匹配下表中的任意字符串,将event类型属性值设置为同一行匹配字符串旁的字符串,否则返回。

      事件类型 旧式事件类型
      "animationend" "webkitAnimationEnd"
      "animationiteration" "webkitAnimationIteration"
      "animationstart" "webkitAnimationStart"
      "transitionend" "webkitTransitionEnd"
    3. 内部调用通过eventlisteners阶段invocationTargetInShadowTree,以及如果给出的话legacyOutputDidListenersThrowFlag

    4. event类型属性值设置为originalEventType

内部调用,给定一个eventlisteners阶段invocationTargetInShadowTree,以及可选的legacyOutputDidListenersThrowFlag,请运行这些步骤:

  1. found 为 false。

  2. 对于 listeners 中的每个 listener,其 removed 为 false:

    1. 如果 eventtype 属性值不是 listener类型,则 继续

    2. found 设为 true。

    3. 如果 phase 是 "capturing" 并且 listenercapture 为 false,则 继续

    4. 如果 phase 是 "bubbling" 并且 listenercapture 为 true,则 继续

    5. 如果 listeneronce 为 true,则根据 eventcurrentTarget 属性值和 listener 移除一个事件侦听器

    6. global 成为 listener回调关联的领域全局对象

    7. currentEvent 为 undefined。

    8. 如果 global 是一个 Window 对象:

      1. currentEvent 设为 global当前事件

      2. 如果 invocationTargetInShadowTree 为 false,则将 global当前事件 设为 event

    9. 如果 listenerpassive 为 true,则设定 event被动监听器标志

    10. 如果 global 是一个 Window 对象,则 记录事件监听器的计时信息,使用 eventlistener

    11. 调用用户对象的操作,使用 listener回调,"handleEvent",«event»,以及 eventcurrentTarget 属性值。如果这会抛出一个异常 exception

      1. 报告 exception,用于 listener回调的相应 JavaScript 对象的 关联领域全局对象

      2. 设置 legacyOutputDidListenersThrowFlag(如果提供)。

        legacyOutputDidListenersThrowFlag 仅被 Indexed Database API 使用。[INDEXEDDB]

    12. 取消设定 event被动监听器标志

    13. 如果 global 是一个 Window 对象,则将 global当前事件 设为 currentEvent

    14. 如果 event停止立即传播标志已设置,则中断

  3. 返回 found

2.10. 触发事件

要在target触发事件,事件名为e,可选地使用eventConstructor,并描述如何初始化IDL属性,以及legacy target override flag,请执行以下步骤:

  1. 如果未给出eventConstructor,则令eventConstructorEvent

  2. event为根据eventConstructor 创建事件的结果,且在target相关领域中。

  3. eventtype属性初始化为e

  4. 按照此算法调用时描述的内容初始化event的其他IDL属性。

    这也允许将isTrusted属性设置为false。

  5. 返回调度eventtarget的结果,并在设置时设置legacy target override flag

在 DOM 的上下文中,"Fire" 是创建、初始化和分派一个事件的缩写。Fire an event 使得这个过程更容易表达。

如果事件需要其 bubblescancelable 属性初始化, 可以这样写:“fire an event named submit at target with its cancelable attribute initialized to true”。

或者,当需要自定义构造函数时,可以这样写:“fire an event named click at target using MouseEvent with its detail attribute initialized to 1”。

有时返回值很重要:

  1. doAction 成为 firing an event named like at target 的结果。

  2. 如果 doAction 为真,那么……

2.11. 行为与发生

一个事件表示一次发生,而不是一个行为。换句话说,它 代表来自算法的通知,并可用于影响该算法的未来进程 (例如,通过调用 preventDefault())。 事件不得 用作导致某些算法开始运行的行为或发起者。那不是 它们的用途。

在此特别指出这一点,是因为 DOM 的先前迭代具有与事件关联的“默认行为”概念,这给人们带来了所有错误的想法。事件不代表或导致行为,它们 只能用于影响正在进行的行为。

3. 中止正在进行的活动

尽管 promise 没有内置的中止机制,但许多使用它们的 API 都需要中止语义。AbortController 旨在通过提供一个 abort() 方法来支持这些要求,该方法可以切换相应 AbortSignal 对象的状态。希望支持中止的 API 可以接受一个 AbortSignal 对象,并使用其状态来确定如何继续。

鼓励依赖 AbortController 的 API 通过使用 AbortSignal中止原因来拒绝任何未解决的 promise,从而响应 abort()

一个假设的doAmazingness({ ... })方法可以通过接受AbortSignal对象来支持中止,类似如下:

const controller = new AbortController();
const signal = controller.signal;

startSpinner();

doAmazingness({ ..., signal })
  .then(result => ...)
  .catch(err => {
    if (err.name == 'AbortError') return;
    showUserErrorMessage();
  })
  .then(() => stopSpinner());

// …

controller.abort();

doAmazingness could be implemented as follows:

function doAmazingness({signal}) {
  return new Promise((resolve, reject) => {
    signal.throwIfAborted();

    // Begin doing amazingness, and call resolve(result) when done.
    // But also, watch for signals:
    signal.addEventListener('abort', () => {
      // Stop doing amazingness, and:
      reject(signal.reason);
    });
  });
}

不返回promise的API可以选择以类似的方式做出反应,或者选择完全不展示AbortSignal中止原因addEventListener()就是一个适合后者的API例子。

需要更精细控制的API可以根据需要扩展AbortControllerAbortSignal对象。

3.1. 接口 AbortController

[Exposed=*]
interface AbortController {
  constructor();

  [SameObject] readonly attribute AbortSignal signal;

  undefined abort(optional any reason);
};
controller = new AbortController()
返回一个新的controller,其signal被设置为新创建的AbortSignal对象。
controller . signal
返回与此对象关联的AbortSignal对象。
controller . abort(reason)
调用此方法将把reason存储在此对象的AbortSignal中止原因中,并向任何观察者发出信号,表示相关活动将被中止。如果reason未定义,则会存储一个"AbortError"DOMException

一个AbortController对象有一个关联的信号(一个AbortSignal对象)。

new AbortController()构造函数步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. 设置thissignalsignal

signal的getter步骤是返回thissignal

abort(reason)方法步骤是在signal abort上执行,带有reason如果给定。

AbortControllercontroller上带有可选的reason执行signal abort,如果reason被提供。

3.2. 接口AbortSignal

[Exposed=*]
interface AbortSignal : EventTarget {
  [NewObject] static AbortSignal abort(optional any reason);
  [Exposed=(Window,Worker), NewObject] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds);
  [NewObject] static AbortSignal _any(sequence<AbortSignal> signals);

  readonly attribute boolean aborted;
  readonly attribute any reason;
  undefined throwIfAborted();

  attribute EventHandler onabort;
};
AbortSignal . abort(reason)
返回一个AbortSignal实例,其中止原因设置为reason(如果未定义则为"AbortError"DOMException)。
AbortSignal . any(signals)
返回一个AbortSignal实例,该实例将在任一signals中止时中止。其中止原因将被设置为导致中止的signals中的某一个。
AbortSignal . timeout(milliseconds)
返回一个AbortSignal实例,该实例将在milliseconds毫秒后中止。其中止原因将被设置为"TimeoutError"DOMException
signal . aborted
如果signalAbortController已发出中止信号,则返回true;否则返回false。
signal . reason
返回signal中止原因
signal . throwIfAborted()
如果signalAbortController已发出中止信号,则抛出signal中止原因;否则不执行任何操作。

一个AbortSignal对象有一个关联的中止原因(一个JavaScript值),其初始状态为未定义。

一个AbortSignal对象有一个关联的中止算法(一组将在中止时执行的算法),其初始状态为空。

中止算法使得具有复杂要求的API能够合理地响应abort()。例如,给定API的中止原因可能需要传播到跨线程环境,例如service worker。

一个AbortSignal对象有一个依赖项(一个布尔值),其初始状态为false。

一个AbortSignal对象有一个关联的源信号(一组AbortSignal对象),其初始状态为空。

一个AbortSignal对象有一个关联的依赖信号(一组依赖于对象的AbortSignal对象),其初始状态为空。


静态方法abort(reason)的步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. signal中止原因设置为reason,如果给定;否则设置为新的"AbortError"DOMException

  3. 返回signal

静态方法timeout(milliseconds)的步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. global成为signal相关全局对象

  3. 在超时后运行步骤,给定global、"AbortSignal-timeout"、milliseconds,以及以下步骤:

    1. 在全局任务队列中排队,在global上,基于signal和新的"TimeoutError"DOMException执行signal abort

    在此超时时间内,如果signal已为其abort事件注册了任何事件监听器,则必须从globalsignal保持一个强引用。

  4. 返回signal

静态方法any(signals)的步骤是返回创建一个依赖的中止信号的结果,使用signalsAbortSignal当前领域

abortedgetter步骤是返回true如果this中止;否则返回false。

reasongetter步骤是返回this中止原因

throwIfAborted()方法步骤是抛出this中止原因,如果this中止

此方法主要用于当接受AbortSignal的函数希望在特定检查点抛出(或返回一个被拒绝的promise),而不是将AbortSignal传递给其他方法时。例如,以下函数允许在每次尝试轮询条件之间中止。这为中止轮询过程提供了机会,即使实际的异步操作(即await func())不接受AbortSignal

async function waitForCondition(func, targetValue, { signal } = {}) {
  while (true) {
    signal?.throwIfAborted();

    const result = await func();
    if (result === targetValue) {
      return;
    }
  }
}

属性 onabort 是一个 事件处理程序 IDL 属性,用于 onabort 事件处理程序,其 事件处理程序事件类型abort

AbortSignal 对象的更改代表了相应的 AbortController 对象的意图,但观察 AbortSignal 对象的 API 可以选择忽略这些更改。例如,如果操作已经完成。


AbortSignal 对象的 中止原因 不为未定义时, 该对象被认为是 已中止

要向 AbortSignal 对象 signal添加 一个算法 algorithm

  1. 如果 signal中止,则返回。

  2. algorithm 追加到 signal中止算法中。

要从 AbortSignal signal移除一个算法 algorithm,请从 signal中止算法移除 algorithm

发出中止信号, 给定一个 AbortSignal 对象 signal 和一个可选的 reason

  1. 如果 signal 已经 中止,则返回。

  2. signal中止原因 设为 reason(如果提供);否则设为一个新的 "AbortError" DOMException

  3. dependentSignalsToAbort 设为一个新的 列表

  4. 对于每个 dependentSignalsignal依赖信号 中:

    1. 如果 dependentSignal 尚未 中止

      1. dependentSignal中止原因 设为 signal中止原因

      2. 附加 dependentSignaldependentSignalsToAbort

  5. 运行中止步骤 对于 signal

  6. 对于每个 dependentSignaldependentSignalsToAbort 中,运行中止步骤 对于 dependentSignal

运行中止步骤 对于一个 AbortSignal signal

  1. 对于每个 algorithmsignal中止算法 中:运行 algorithm

  2. 清空 signal中止算法

  3. 触发事件,名为 abort,在 signal 上。

要从 AbortSignal 对象列表 signals 创建一个依赖中止信号,使用 signalInterface(它必须是 AbortSignal 或继承自它的接口)和一个 realm

  1. resultSignal 为一个使用 realm 实现 signalInterface对象。

  2. 对于 signals 中的每个 signal:如果 signal中止,则将 resultSignal中止原因设置为 signal中止原因并返回 resultSignal

  3. resultSignal依赖属性设置为 true。

  4. 对于 signals 中的每个 signal

    1. 如果 signal依赖属性为 false:

      1. signal 追加resultSignal源信号列表中。

      2. resultSignal 追加signal依赖信号列表中。

    2. 否则,对于 signal源信号列表中的每个 sourceSignal

      1. 断言:sourceSignal中止 且其依赖属性不为 true。

      2. sourceSignal 追加resultSignal源信号列表中。

      3. resultSignal 追加sourceSignal依赖信号列表中。

  5. 返回 resultSignal

3.2.1. 垃圾回收

一个未中止依赖的 AbortSignal 对象,当其源信号列表非空并且它已为其 abort 事件注册了事件监听器或者其中止算法列表非空时,不能被垃圾回收。

3.3. 在 API 中使用 AbortControllerAbortSignal 对象

任何使用 promises 表示可以中止操作的 Web 平台 API 必须遵循以下规则:

返回 promise 的方法 doAmazingness(options) 的方法步骤可能如下:

  1. global成为相关全局对象

  2. p成为一个新的 promise

  3. 如果 options["signal"] 存在

    1. signal成为options["signal"]。

    2. 如果 signal已中止, 则拒绝p,使用signal中止原因,并返回 p

    3. 添加以下中止步骤signal

      1. 停止做令人惊叹的事情。

      2. 拒绝p,使用signal中止原因

  4. 并行运行这些步骤:

    1. amazingResult成为做一些令人惊叹的事情的结果。

    2. 在全局任务队列中添加一个任务,任务源为global,以解决p,并将amazingResult作为参数。

  5. 返回 p

不使用 promises 的 API 仍应尽可能遵循上述规则。

4. 节点

4.1. “DOM”简介

在其原始意义上,“DOM”是一个用于访问和操作文档(特别是HTML和XML文档)的API。在本规范中,术语“文档”用于任何基于标记的资源,从简短的静态文档到包含丰富多媒体的长篇文章或报告,以及功能齐全的交互式应用程序。

每个这样的文档都表示为一个节点树中的一些节点可以有子节点,而其他的总是叶子节点。

为了说明这一点,考虑以下HTML文档:

<!DOCTYPE html>
<html class=e>
 <head><title>Aliens?</title></head>
 <body>Why yes.</body>
</html>

它表示如下:

请注意,由于HTML解析的神奇之处,并非所有ASCII空白字符都被转化为文本节点,但总体概念是清晰的。标记进入,节点输出。

可以使用非常棒的Live DOM Viewer来更详细地探索这个问题。

4.2. 节点树

节点是实现了实现Node的对象。节点参与一个称为节点树

实际上,你处理的是更具体的对象。

实现了实现Node的对象也实现了一个继承的接口:DocumentDocumentTypeDocumentFragmentElementCharacterDataAttr

实现了DocumentFragment的对象有时会实现ShadowRoot

实现了Element的对象通常也会实现一个继承的接口,例如HTMLAnchorElement

实现了CharacterData的对象也会实现一个继承的接口:TextProcessingInstructionComment

实现了Text的对象有时会实现CDATASection

因此,每个节点主要接口是以下之一:DocumentDocumentTypeDocumentFragmentShadowRootElementElement的一个继承接口,AttrTextCDATASectionProcessingInstructionComment

为简洁起见,本规范将实现了Node和继承接口NodeInterface的对象称为NodeInterface节点

节点树的限制如下,表示为节点及其潜在子节点之间的关系:

Document

树顺序

  1. 零个或多个ProcessingInstructionComment节点

  2. 可选地包含一个DocumentType节点

  3. 零个或多个ProcessingInstructionComment节点

  4. 可选地包含一个Element节点

  5. 零个或多个ProcessingInstructionComment节点

DocumentFragment
Element

零个或多个ElementCharacterData节点

DocumentType
CharacterData
Attr

没有子节点

Attr 节点因历史原因会参与一棵;它们从不会有(非 null)父节点或任何子节点,因此始终独自处于一棵中。

要确定节点node长度,执行以下步骤:

  1. 如果nodeDocumentTypeAttr节点,则返回 0。

  2. 如果nodeCharacterData 节点,则返回 nodedata长度

  3. 返回 node子节点数量。

节点长度为 0 时,认为该节点是空的

4.2.1. 文档树

文档树是一个节点树,其是一个文档

文档元素是一个文档中其父节点是该文档元素;如果不存在,则为 null。

根据节点树的限制,这样的元素只能有一个。

当一个节点文档时,称该节点处于文档树中

当一个节点处于文档树中时,称其处于文档中术语处于文档中已不再建议使用,若存在该术语,说明所用标准尚未更新以适配影子树

4.2.2. 影子树

影子树是一个节点树,其是一个影子根

影子根总是通过其宿主附加到另一个节点树。因此,影子树永远不会是孤立的。影子根宿主节点树有时被称为光树

一个影子树的相应光树本身可以是一个影子树

当一个节点包含影子的根是一个文档时,该节点被认为是已连接的

4.2.2.1. 插槽

一个影子树包含零个或多个元素,它们是插槽

一个插槽只能通过HTML的slot元素创建。

一个插槽有一个关联的名称(一个字符串)。除非另有说明,否则它是空字符串。

使用这些属性更改步骤来更新一个插槽名称

  1. 如果element是一个插槽localNamename,且namespace为空:

    1. 如果valueoldValue,则返回。

    2. 如果value为null且oldValue为空字符串,则返回。

    3. 如果value为空字符串且oldValue为null,则返回。

    4. 如果value为null或空字符串,则将element名称设置为空字符串。

    5. 否则,将element名称设置为value

    6. 使用element运行为树分配可插槽对象

一个插槽是一个影子树中的第一个,在树顺序中,其名称为空字符串的插槽,有时被称为“默认插槽”。

一个插槽有一个关联的分配的节点(一个可插槽对象的列表)。除非另有说明,否则它是空的。

4.2.2.2. 可插槽对象

元素文本节点可插槽对象

插槽 可以是一个可插槽对象

一个可插槽对象有一个关联的名称(一个字符串)。除非另有说明,否则它是空字符串。

使用这些属性更改步骤来更新可插槽对象名称

  1. 如果localNameslotnamespace为空:

    1. 如果valueoldValue,则返回。

    2. 如果value为null且oldValue为空字符串,则返回。

    3. 如果value为空字符串且oldValue为null,则返回。

    4. 如果value为null或空字符串,则将element名称设置为空字符串。

    5. 否则,将element名称设置为value

    6. 如果element已分配,则为element已分配插槽运行分配可插槽对象

    7. element运行分配插槽

字母A 可插槽元素有一个关联的已分配插槽(null或插槽)。 除非另有说明,否则它为null。字母A 可插槽元素已分配的,如果它的已分配插槽非null。

一个可插槽对象有一个关联的手动插槽分配(null或插槽)。除非另有说明,否则它是null。

一个可插槽对象手动插槽分配可以使用对插槽的弱引用来实现,因为这个变量不能直接从脚本访问。

4.2.2.3. 查找插槽和可插槽对象

查找插槽,对于给定的可插入对象 slottable 和一个可选的布尔值 open(默认为 false):

  1. 如果 slottable父节点为 null,则返回 null。

  2. shadowslottable父节点影子根

  3. 如果 shadow 为 null,则返回 null。

  4. 如果 open 为 true 且 shadow模式不为“open”,则返回 null。

  5. 如果 shadow插槽分配为“manual”,则返回 shadow后代中其手动分配的节点包含 slottable插槽(如果存在);否则返回 null。

  6. 返回 shadow后代中按树顺序排列的第一个其名称slottable名称插槽(如果存在);否则返回 null。

查找可插入对象,对于给定的插槽 slot

  1. result 为 « »。

  2. rootslot

  3. 如果 root 不是影子根,则返回 result

  4. hostroot宿主

  5. 如果 root插槽分配为“manual”:

    1. 对于 slot手动分配的节点中的每个可插入对象 slottable,如果 slottable父节点host,则将 slottable 追加result

  6. 否则,对于 host 的每个可插入对象子节点 slottable,按树顺序

    1. foundSlot 为给定 slottable 查找插槽的结果。

    2. 如果 foundSlotslot,则将 slottable 追加result

  7. 返回 result

查找扁平化可插入对象,对于给定的插槽 slot

  1. result 为 « »。

  2. 如果 slot不是影子根,则返回 result

  3. slottables 为给定 slot 查找可插入对象的结果。

  4. 如果 slottables 是空列表,则将 slot 的每个可插入对象子节点树顺序追加到 slottables

  5. 对于 slottables 中的每个 node

    1. 如果 node 是一个插槽,其是一个影子根

      1. temporaryResult 为给定 node 查找扁平化可插入对象的结果。

      2. temporaryResult 中的每个可插入对象按顺序追加到 result

    2. 否则,将 node 追加到 result

  6. 返回 result

4.2.2.4. 分配可插槽对象和插槽

要为插槽 slot 分配可插入对象

  1. slottables 为为 slot 查找可插入对象的结果。

  2. 如果 slottablesslot已分配节点不相同,则为 slot 运行发出插槽更改信号

  3. slot已分配节点设置为 slottables

  4. 对于 slottables 中的每个 slottable: 将 slottable已分配插槽设置为 slot

为树分配可插入对象,给定一个节点 root,按树顺序root包含后代中的每个插槽运行分配可插入对象

分配插槽,给定一个可插入对象 slottable

  1. slot 为使用 slottable 查找插槽的结果。

  2. 如果 slot 非空,则为 slot 运行分配可插入对象

4.2.2.5. 发出插槽变更信号

每个相同来源窗口代理都有一个信号插槽集合中的一部分插槽),其初始值为空。[HTML]

要为一个插槽 slot 发出插槽更改信号

  1. slot 追加slot相关代理信号插槽列表

  2. 将突变观察者微任务排入队列

4.2.3. 变异算法

在将一个node node 插入到一个node parent 中,在 null 或 node child 之前,确保其插入前有效性

  1. 如果 parent 不是一个 DocumentDocumentFragment,或 Element node,则抛出 一个 "HierarchyRequestError" DOMException

  2. 如果 nodeparenthost-including inclusive ancestor,则抛出 一个 "HierarchyRequestError" DOMException

  3. 如果 child 非 null 且其 parent 不是 parent,则抛出 一个 "NotFoundError" DOMException

  4. 如果 node 不是 DocumentFragmentDocumentTypeElement,或 CharacterData node,则抛出 一个 "HierarchyRequestError" DOMException

  5. 如果 node 是一个 Text nodeparent 是一个 document,或者 node 是一个 doctypeparent 不是 document,则抛出 一个 "HierarchyRequestError" DOMException

  6. 如果 parent 是一个 document,且下列按 node 接口 implements 切换的语句中任一为真,则抛出 一个 "HierarchyRequestError" DOMException

    DocumentFragment

    如果 node 有多于一个的 element child,或有一个 Text node child

    否则,如果 node 有一个 element child 并且任一满足:parent 有一个 element childchild 是一个 doctype,或 child 非 null 且存在一个 doctypechild 之后(following),则为真。

    Element

    如果 parent 有一个 element child,或者 child 是一个 doctype,或者 child 非 null 且存在一个 doctypechild 之后(following),则为真。

    DocumentType

    如果 parent 有一个 doctype childchild 非 null 且有一个 elementchild 之前(preceding),或 child 为 null 且 parent 有一个 element child,则为真。

要将 预插入 一个 node node 插入到 一个 node parent 在 null 或 node child 之前:

  1. 确保插入前有效性:将 node 插入到 parentchild 之前。

  2. referenceChildchild

  3. 如果 referenceChildnode,则将 referenceChild 设为 nodenext sibling

  4. 插入 nodeparent,位于 referenceChild 之前。

  5. 返回 node

其他规范 可能为全部或部分nodes 定义插入步骤。该算法接收 insertedNode,如下面的 insert 算法所示。这些步骤不得修改 insertedNode 所参与的节点树、创建浏览上下文(browsing contexts)、触发事件,或以其他方式执行 JavaScript。然而,这些步骤可以通过排队任务来异步完成这些操作。

尽管 插入步骤 不能执行 JavaScript(以及其他限制),它们仍会对脚本可观测产生影响。考虑下面的示例:

const h1 = document.querySelector('h1');

const fragment = new DocumentFragment();
const script = fragment.appendChild(document.createElement('script'));
const style = fragment.appendChild(document.createElement('style'));

script.innerText= 'console.log(getComputedStyle(h1).color)'; // Logs 'rgb(255, 0, 0)'
style.innerText = 'h1 {color: rgb(255, 0, 0);}';

document.body.append(fragment);

上例中的脚本记录了 'rgb(255, 0, 0)',因为以下步骤按顺序发生:

  1. insert 算法运行,会将 scriptstyle 元素按顺序插入。

    1. HTML 标准中针对 script 元素的 插入步骤 运行;它们不做任何事情。[HTML]

    2. HTML 标准中针对 style 元素的 插入步骤 运行;它们立即将其样式规则应用到文档中。[HTML]

    3. HTML 标准中针对 script 元素的 后连接步骤 运行;它们运行脚本,脚本会立即观察到上一步应用的样式规则。[HTML]

其他规范 也可能为全部或部分nodes 定义后连接步骤。该算法接收 connectedNode,如下面的 insert 算法所示。

后连接步骤 的目的是为节点提供在连接时执行任何与连接相关的操作的机会,这些操作可能会修改 connectedNode 所参与的节点树、创建浏览上下文,或以其他方式执行 JavaScript。这些步骤允许一批节点 就脚本而言以原子方式插入,所有主要副作用都发生在批量插入到节点树 完成之后。这确保了所有待处理的节点树插入在更多插入发生之前完全完成。

其他规范 可能为全部或部分nodes 定义子节点变更步骤。该算法不接收参数,并由insertremove 以及 replace data 调用。

要将 insert 一个 node node 插入到 一个 node parent,在 null 或 一个 node child 之前,可选地带有布尔值 suppressObservers(默认 false):

  1. nodesnodechildren(如果 nodeDocumentFragment node);否则为 « node »。

  2. countnodessize

  3. 如果 count 为 0,则返回。

  4. 如果 nodeDocumentFragment node

    1. suppressObservers 为 true 的方式移除children

    2. node 排队一个树突变记录,参数为 « », nodes, null, null。

      此步骤有意不考虑 suppressObservers

  5. 如果 child 非 null:

    1. 对于每个其 start nodeparentstart offset 大于 childindexlive range:将其 start offset 增加 count

    2. 对于每个其 end nodeparentend offset 大于 childindexlive range:将其 end offset 增加 count

  6. previousSiblingchildprevious sibling,若 child 为 null 则为 parentlast child

  7. 对于 nodes 中按 树序 的每个 node

    1. node 采纳到 parentnode document 中。

    2. 如果 child 为 null,则 node 追加到 parentchildren

    3. 否则, node 插入到 parentchildren 中,位置在 childindex 之前。

    4. 如果 parent 是一个其 shadow rootshadow host,且该 shadow root 的 slot assignment 为 "named",并且 node 是一个 slottable,则为 node 分配一个 slot

    5. 如果 parentroot 是一个 shadow root,且 parent 是一个 slot,且其 assigned nodes 为空列表,则为 parent 运行 signal a slot change

    6. 运行 为树分配 slottables,参数为 noderoot

    7. 对于 node 的每个 shadow-including inclusive descendant inclusiveDescendant,按 shadow-including 树序

      1. inclusiveDescendant 运行 插入步骤

      2. 如果 inclusiveDescendantconnected,则 继续

      3. 如果 inclusiveDescendant 是一个 element 且其 custom element registry 非 null:

        1. 如果该 inclusiveDescendantcustom element registryis scoped 为 true,则 inclusiveDescendantnode document 追加到其 custom element registryscoped document set

        2. 如果 inclusiveDescendantcustom,则排队一个 custom element callback reaction,参数为 inclusiveDescendant、回调名 "connectedCallback",以及 « »。

        3. 否则,尝试升级 inclusiveDescendant

          如果这成功升级了 inclusiveDescendant,则在 upgrade an element 算法期间,connectedCallback 会被自动排队。

      4. 否则,如果 inclusiveDescendant 是一个 shadow root,且其 custom element registry 非 null,且该 registry 的 is scoped 为 true,则 inclusiveDescendantnode document 追加到其 custom element registryscoped document set

  8. 如果 suppressObservers 为 false,则为 parent 排队一个树突变记录,参数为 nodes, « », previousSibling, child

  9. parent 运行 children changed steps

  10. staticNodeList 为一个列表,初始为 « »,包含 nodes

    我们在对任何一个节点调用 post-connection steps 之前先收集所有 nodes,而不是在遍历节点树时边遍历边调用 post-connection steps。这是因为 post-connection steps 可以修改树的结构,使得对实时遍历不安全,可能导致 post-connection steps 对同一节点 被多次调用。

  11. 对于 nodes 中按 树序 的每个 node

    1. 对于该 node 的每个 shadow-including inclusive descendant inclusiveDescendant,按 shadow-including 树序 inclusiveDescendant 追加到 staticNodeList

  12. 对于 staticNodeList 中的每个 node(参见 For each):如果 nodeconnected,则对 node 运行 post-connection steps

要将节点 node 追加节点 parent预插入 nodeparent 中,插入位置为 null 之前。


其他规范 可能为全部或部分nodes 定义移动步骤。该算法接收一个node movedNode,和一个可能为 null 的node-或-null oldParent,如下面的 move 算法所示。与 插入步骤 类似,这些步骤不得修改 movedNode 所参与的节点树、创建浏览上下文、触发事件或以其他方式执行 JavaScript。不过,这些步骤可以排队任务以异步执行这些操作。

要将 移动 一个 node node 进入 一个 node newParent,在 null 或 一个 node child 之前:

  1. 如果 newParentshadow-including rootnodeshadow-including root 不同,则抛出 一个 "HierarchyRequestError" DOMException

    这有副作用,确保只有当 newParentconnectednodeconnected 相同时才执行移动。

  2. 如果 nodenewParenthost-including inclusive ancestor,则抛出 一个 "HierarchyRequestError" DOMException

  3. 如果 child 非 null 且其 parent 不是 newParent,则抛出 一个 "NotFoundError" DOMException

  4. 如果 node 既不是 Element 也不是 CharacterData node,则抛出 一个 "HierarchyRequestError" DOMException

  5. 如果 node 是一个 Text nodenewParent 是一个 document,则抛出 一个 "HierarchyRequestError" DOMException

  6. 如果 newParent 是一个 document,且 node 是一个 Element node,并且任一:newParent 有一个 element childchilddoctype,或 child 非 null 且有一个 doctypechild 之后(following),则抛出 一个 "HierarchyRequestError" DOMException

  7. oldParentnodeparent

  8. 断言:oldParent 非 null。

  9. 运行 live range pre-remove steps,参数为 node

  10. 对于每个其 rootnode documentnode 相同的 NodeIterator 对象 iterator:对 iterator 运行 NodeIterator pre-remove steps,参数为 nodeiterator

  11. oldPreviousSiblingnodeprevious sibling

  12. oldNextSiblingnodenext sibling

  13. oldParentchildren 中移除 node

  14. 如果 nodeassigned,则为其 assigned slot 运行 assign slottables

  15. 如果 oldParentroot 是一个 shadow root,且 oldParent 是一个 slot,且其 assigned nodes 为空,则为 oldParent 运行 signal a slot change

  16. 如果 node 有一个作为 slotinclusive descendant

    1. oldParentroot 运行 assign slottables for a tree

    2. node 运行 assign slottables for a tree

  17. 如果 child 非 null:

    1. 对于每个其 start nodenewParentstart offset 大于 childindexlive range:将其 start offset 增加 1。

    2. 对于每个其 end nodenewParentend offset 大于 childindexlive range:将其 end offset 增加 1。

  18. newPreviousSibling 为当 child 非 null 时 childprevious sibling,否则为 newParentlast child

  19. 如果 child 为 null,则 node 追加到 newParentchildren

  20. 否则, node 插入到 newParentchildren,位置在 childindex 之前。

  21. 如果 newParent 是一个其 shadow rootshadow host,且该 shadow root 的 slot assignment 为 "named",并且 node 是一个 slottable,则为 node 分配一个 slot

  22. 如果 newParentroot 是一个 shadow root,且 newParent 是一个 slot,且其 assigned nodes 为空,则为 newParent 运行 signal a slot change

  23. 运行 为树分配 slottables,参数为 noderoot

  24. 对于 node 的每个 shadow-including inclusive descendant inclusiveDescendant,按 shadow-including 树序

    1. 如果 inclusiveDescendantnode,则对其运行 moving steps,参数为 inclusiveDescendantoldParent。否则,对其运行 moving steps,参数为 inclusiveDescendant 和 null。

      因为 move 算法与 insertremove 是独立的原语,所以它不会为 inclusiveDescendant 调用传统的 插入步骤移除步骤

    2. 如果 inclusiveDescendantcustomnewParentconnected,则为 inclusiveDescendant 排队一个 custom element callback reaction,回调名为 "connectedMoveCallback",参数为 « »。

  25. oldParent 排队一个树突变记录,参数为 « », « node », oldPreviousSibling, oldNextSibling

  26. newParent 排队一个树突变记录,参数为 « node », « », newPreviousSibling, child


替换 一个 节点 child 为 一个 节点 node 在 一个 节点 parent

  1. 如果 parent 不是 DocumentDocumentFragment,或 Element node,则抛出 一个 "HierarchyRequestError" DOMException

  2. 如果 nodeparenthost-including inclusive ancestor,则抛出 一个 "HierarchyRequestError" DOMException

  3. 如果 childparent 不是 parent,则抛出 一个 "NotFoundError" DOMException

  4. 如果 node 不是 DocumentFragmentDocumentTypeElement,或 CharacterData node,则抛出 一个 "HierarchyRequestError" DOMException

  5. 如果 node 是一个 Text nodeparent 是一个 document,或者 node 是一个 doctypeparent 不是 document,则抛出 一个 "HierarchyRequestError" DOMException

  6. 如果 parent 是一个 document,且下列按 node 接口 implements 切换的语句中任一为真,则抛出 一个 "HierarchyRequestError" DOMException

    DocumentFragment

    如果 node 有多于一个的 element child,或有一个 Text node child

    否则,如果 node 有一个 element child 并且任一条件成立:parent 有一个不是 childelement child,或存在一个 doctypechild 之后(following),则为真。

    Element

    如果 parent 有一个不是 childelement child,或存在一个 doctypechild 之后(following),则为真。

    DocumentType

    如果 parent 有一个不是 childdoctype child,或存在一个 elementchild 之前(preceding),则为真。

    上述陈述与 pre-insert 算法不同。

  7. referenceChildchildnext sibling

  8. 如果 referenceChildnode,则将 referenceChild 设为 nodenext sibling

  9. previousSiblingchildprevious sibling

  10. removedNodes 为空集合。

  11. 如果 childparent 非 null:

    1. removedNodes 设为 « child »。

    2. suppressObservers 为 true 的方式移除 child

    上述情况仅在 childnode 时才可能为假。

  12. nodes 为:如果 nodeDocumentFragment node,则为其 children;否则为 « node »。

  13. node 插入到 parentreferenceChild 之前,且以 suppressObservers 为 true 的方式执行。

  14. parent 排队一个树突变记录,参数为 nodes, removedNodes, previousSibling, referenceChild

  15. 返回 child

要在一个node parent 中用一个node 或 null node 执行 replace all

  1. removedNodesparentchildren

  2. addedNodes 为空集合。

  3. 如果 nodeDocumentFragment node,则将 addedNodes 设为 nodechildren

  4. 否则,如果 node 非 null,则将 addedNodes 设为 « node »。

  5. suppressObservers 为 true 的方式移除 parent 的所有 children(按树序)。

  6. 如果 node 非 null,则以 插入 的方式将 node 插入到 parent 的 null 之前,且以 suppressObservers 为 true 的方式执行。

  7. 如果 addedNodesremovedNodes 中任一不为空(参见 is not empty),则为 parent 排队一个树突变记录,参数为 addedNodes, removedNodes, null, null。

此算法对节点树 约束不做任何检查。规范作者需谨慎使用。


要从一个node parent 中预移除一个node childpre-remove):

  1. 如果 childparent 不是 parent,则抛出 一个 "NotFoundError" DOMException

  2. 移除 child

  3. 返回 child

其他规范 可能为全部或部分nodes 定义移除步骤。该算法接收一个node removedNode 和 一个可能为 null 的 node oldParent,如下面的 remove 算法所示。

移除一个节点node,可选布尔参数 suppressObservers(默认为 false):

  1. parentnodeparent

  2. 断言:parent 非 null。

  3. 运行 live range pre-remove steps,参数为 node

  4. 对于每个其 rootnode documentnode 相同的 NodeIterator 对象 iterator:对 iterator 运行 NodeIterator pre-remove steps,参数为 nodeiterator

  5. oldPreviousSiblingnodeprevious sibling

  6. oldNextSiblingnodenext sibling

  7. parentchildren 中移除 node

  8. 如果 nodeassigned,则为其 assigned slot 运行 assign slottables

  9. 如果 parentroot 是一个 shadow root,且 parent 是一个 slot,且其 assigned nodes 为空,则为 parent 运行 signal a slot change

  10. 如果 node 有一个作为 slotinclusive descendant

    1. parentroot 运行 assign slottables for a tree

    2. node 运行 assign slottables for a tree

  11. nodeparent 运行 removing steps

  12. isParentConnectedparentconnected

  13. 如果 nodecustomisParentConnected 为 true,则为 node 排队一个 custom element callback reaction,回调名为 "disconnectedCallback",参数为 « »。

    目前有意不向 custom elements 传递 parent。如有需要,未来可能会更改。

  14. 对于 node 的每个 shadow-including descendant descendant,按 shadow-including 树序

    1. descendantdescendant 和 null 为参数运行 removing steps

    2. 如果 descendantcustomisParentConnected 为 true,则为 descendant 排队一个 custom element callback reaction,回调名为 "disconnectedCallback",参数为 « »。

  15. 对于 parent 的每个 inclusive ancestor inclusiveAncestor,以及对其每个 registered(来自其 registered observer list),如果该 registeredoptions["subtree"] 为 true,则添加 一个新的 transient registered observer,其 observer 为该 registeredobserveroptions 为该 registeredoptions,且 source 为该 registerednoderegistered observer list

  16. 如果 suppressObservers 为 false,则为 parent 排队一个树突变记录,参数为 « », « node », oldPreviousSibling, oldNextSibling

  17. parent 运行 children changed steps

4.2.4. 混入 NonElementParentNode

出于 Web 兼容性的考虑,阻止 getElementById() 方法在 elements 上被暴露(因此也不会在 ParentNode 上暴露)。

interface mixin NonElementParentNode {
  Element? getElementById(DOMString elementId);
};
Document includes NonElementParentNode;
DocumentFragment includes NonElementParentNode;
node . getElementById(elementId)

返回 node后代IDelementId 的第一个元素

The getElementById(elementId) 方法的步骤是返回在 树顺序(tree order) 中、位于 this后代(descendants) 中的第一个 元素(element),且该元素的 IDelementId;否则,如果不存在这样的 元素(element),则返回 null。

4.2.5. Mixin DocumentOrShadowRoot

interface mixin DocumentOrShadowRoot {
  readonly attribute CustomElementRegistry? customElementRegistry;
};
Document includes DocumentOrShadowRoot;
ShadowRoot includes DocumentOrShadowRoot;
registry = documentOrShadowRoot . customElementRegistry

返回 documentOrShadowRootCustomElementRegistry 对象(如果存在); 否则返回 null。

customElementRegistry getter 的步骤是:

  1. 如果此对象是一个文档, 则返回此对象自定义元素注册表

  2. 断言此对象是一个 ShadowRoot 节点

  3. 返回此对象自定义元素注册表

DocumentOrShadowRoot mixin 也期望被其他想要定义文档影子根之间共享 API 的标准使用。

4.2.6. Mixin ParentNode

将 nodes 转换为一个 node,给定一个列表节点和字符串 nodes,以及document document

  1. nodes 中的每个字符串替换为一个新的 Text 节点,其数据为该字符串,节点文档document

  2. 如果 nodes长度为 1,则返回 nodes[0]。

  3. fragment 为一个新的 DocumentFragment 节点,其节点文档document

  4. 对于 nodes 中的每个 node node 添加到 fragment

  5. 返回 fragment

interface mixin ParentNode {
  [SameObject] readonly attribute HTMLCollection children;
  readonly attribute Element? firstElementChild;
  readonly attribute Element? lastElementChild;
  readonly attribute unsigned long childElementCount;

  [CEReactions, Unscopable] undefined prepend((Node or DOMString)... nodes);
  [CEReactions, Unscopable] undefined append((Node or DOMString)... nodes);
  [CEReactions, Unscopable] undefined replaceChildren((Node or DOMString)... nodes);

  [CEReactions] undefined moveBefore(Node node, Node? child);

  Element? querySelector(DOMString selectors);
  [NewObject] NodeList querySelectorAll(DOMString selectors);
};
Document includes ParentNode;
DocumentFragment includes ParentNode;
Element includes ParentNode;
collection = node . children
返回 元素
element = node . firstElementChild
返回第一个作为 子节点元素,否则为 null。
element = node . lastElementChild
返回最后一个作为 子节点元素,否则为 null。
node . prepend(nodes)

node第一个子节点之前插入 nodes,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树的约束,则抛出 "HierarchyRequestError" DOMException

node . append(nodes)

node最后一个子节点之后插入 nodes,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树的约束,则抛出 "HierarchyRequestError" DOMException

node . replaceChildren(nodes)

nodes 替换 node 的所有 子节点,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树的约束,则抛出 "HierarchyRequestError" DOMException

node . moveBefore(movedNode, child)

如果 child 不为 null,则在 child 之后将 movedNode 移动到 node 内部;否则在 node最后一个子节点后面移动。此方法会保留与 movedNode 相关的状态。

如果违反了 节点树的约束,或无法保留与移动节点相关的状态,则抛出 "HierarchyRequestError" DOMException

node . querySelector(selectors)

返回第一个作为 后代元素,该元素属于 node 并且匹配 selectors

node . querySelectorAll(selectors)

返回作为 后代的所有 元素,且这些元素属于 node 并且匹配 selectors

children 的 getter 步骤是:返回一个以 collection 形式、以 this 为根节点,仅匹配 元素 子节点HTMLCollection

firstElementChild 的 getter 步骤是:返回第一个作为 子节点元素,否则为 null。

lastElementChild 的 getter 步骤是:返回最后一个作为 子节点元素,否则为 null。

childElementCount 的 getter 步骤是:返回 this 的子节点中为 元素 的数量。

prepend(nodes) 方法步骤:

  1. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  2. 预插入 nodethis,位置在 this第一个子节点之前。

append(nodes) 方法步骤:

  1. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  2. 追加 nodethis

replaceChildren(nodes) 方法步骤:

  1. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  2. 确保预插入有效性,让 nodethis 里的 null 位置插入。

  3. 全部替换,使用 node 替换 this 里的内容。

moveBefore(node, child) 方法步骤:

  1. referenceChild 等于 child

  2. 如果 referenceChild 等于 node,则将 referenceChild 设为 node下一个兄弟节点

  3. 移动 nodethis,位置在 referenceChild 之前。

querySelector(selectors) 方法步骤是:若运行 作用域匹配选择器字符串 selectors 作用于 this 得到的结果不为空,则返回第一个结果;否则返回 null。

querySelectorAll(selectors) 方法步骤是:返回运行 作用域匹配选择器字符串 selectors 作用于 this 后得到的 静态集合结果。

4.2.7. 混入 NonDocumentTypeChildNode

Web 兼容性阻止了 previousElementSiblingnextElementSibling 特性在文档类型上公开(因此也在 ChildNode 上公开)。

interface mixin NonDocumentTypeChildNode {
  readonly attribute Element? previousElementSibling;
  readonly attribute Element? nextElementSibling;
};
Element includes NonDocumentTypeChildNode;
CharacterData includes NonDocumentTypeChildNode;
element = node . previousElementSibling
返回作为元素的第一个前置兄弟节点; 否则返回 null。
element = node . nextElementSibling
返回作为元素的第一个后续兄弟节点; 否则返回 null。

previousElementSibling 的 getter 步骤是:返回第一个作为 前序 兄弟节点元素;否则为 null。

nextElementSibling 的 getter 步骤是:返回第一个作为 后序 兄弟节点元素;否则为 null。

4.2.8. 混入 ChildNode

interface mixin ChildNode {
  [CEReactions, Unscopable] undefined before((Node or DOMString)... nodes);
  [CEReactions, Unscopable] undefined after((Node or DOMString)... nodes);
  [CEReactions, Unscopable] undefined replaceWith((Node or DOMString)... nodes);
  [CEReactions, Unscopable] undefined remove();
};
DocumentType includes ChildNode;
Element includes ChildNode;
CharacterData includes ChildNode;
node . before(...nodes)

node 之前插入 nodes,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树 的约束,则抛出 "HierarchyRequestError" DOMException

node . after(...nodes)

node 之后插入 nodes,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树 的约束,则抛出 "HierarchyRequestError" DOMException

node . replaceWith(...nodes)

nodes 替换 node,并将 nodes 中的字符串替换为对应的 Text 节点

如果违反了 节点树 的约束,则抛出 "HierarchyRequestError" DOMException

node . remove()
移除 node

before(nodes) 方法步骤:

  1. parentthis父节点

  2. 如果 parent 为 null,则返回。

  3. viablePreviousSiblingthis 首个 前序 兄弟节点,且不在 nodes 内,否则为 null。

  4. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  5. 如果 viablePreviousSibling 为 null,则设为 parent第一个子节点;否则设为 viablePreviousSibling下一个兄弟节点

  6. 预插入 nodeparent,位置在 viablePreviousSibling 之前。

after(nodes) 方法步骤:

  1. parentthis父节点

  2. 如果 parent 为 null,则返回。

  3. viableNextSiblingthis 首个 后序 兄弟节点,且不在 nodes 内,否则为 null。

  4. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  5. 预插入 nodeparent,位置在 viableNextSibling 之前。

replaceWith(nodes) 方法步骤:

  1. parentthis父节点

  2. 如果 parent 为 null,则返回。

  3. viableNextSiblingthis 首个 后序 兄弟节点,且不在 nodes 内,否则为 null。

  4. node 为调用 将 nodes 转换为一个 node、参数为 nodesthis节点文档 的结果。

  5. 如果 this父节点parent替换 thisnode,在 parent 内。

    this 本可以被插入到 node 里。

  6. 否则 预插入 nodeparent,位置在 viableNextSibling 之前。

remove() 方法步骤:

  1. 如果 this父节点为 null,则返回。

  2. 移除 this

4.2.9. 混入 Slottable

interface mixin Slottable {
  readonly attribute HTMLSlotElement? assignedSlot;
};
Element includes Slottable;
Text includes Slottable;

assignedSlot 的 getter 步骤为:返回以 寻找插槽,传入 this 和 true 的结果。

4.2.10. 旧式集合:NodeListHTMLCollection

集合(collection) 是一个表示 节点列表的对象。 集合可以是 实时(live)静态(static)。 除非另有说明,集合必须是实时的。

如果集合实时的, 那么该对象上的属性和方法必须针对实际底层数据操作,而不是数据快照。

集合创建时,会与其关联一个筛选器和一个根节点。

然后集合 代表 一个以集合根节点为根的子树视图,仅包含与指定筛选器匹配的节点。该视图是线性的。如果没有特殊要求,集合内的节点必须按树顺序排列。

4.2.10.1. 接口 NodeList

一个 NodeList 对象是一个节点集合

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};
collection . length
返回集合中的节点数量。
element = collection . item(index)
element = collection[index]
返回集合中索引为 index节点。节点按树顺序排列。

该对象的 受支持属性索引是从零到集合中节点数量减一的数字范围。如果没有这样的元素,则没有 受支持属性索引

length 属性必须返回集合所代表的节点数量。

item(index) 方法必须返回集合中第 index节点。如果没有第 index节点,则该方法必须返回 null。

4.2.10.2. 接口HTMLCollection
[Exposed=Window, LegacyUnenumerableNamedProperties]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

一个 HTMLCollection 对象是一个元素集合

HTMLCollection 是一个我们无法从 Web 中摆脱的历史产物。 虽然当然欢迎开发人员继续使用它,但新的 API 标准设计者不应该使用它(而应在 IDL 中使用 sequence<T>)。

collection . length
返回集合元素的数量。
element = collection . item(index)
element = collection[index]
集合中返回索引为 index元素元素树顺序排序。
element = collection . namedItem(name)
element = collection[name]
从集合中返回ID 或名称为 name 的第一个元素

对象的支持的属性索引是从零到元素数量减一的范围内的数字由集合表示。如果没有这样的元素,那么就没有支持的属性索引

length获取器步骤应返回由集合表示的节点数量。

item(index) 方法的步骤是:返回集合中的第 index元素。如果集合中没有第 index元素,则该方法必须返回 null。

支持的属性名称是通过以下步骤返回的列表中的值:

  1. result为一个空列表。

  2. 对于集合中由集合表示的每个element,按树顺序处理:

    1. 如果element具有一个不在result中的ID,则将elementID添加到result中。

    2. 如果element位于HTML命名空间中,并且具有一个name属性,且其既不是空字符串也不在result中,则将elementname属性的值添加到result中。

  3. 返回result

namedItem(key)方法步骤是:

  1. 如果 key 是空字符串,则返回 null。

  2. 返回集合中满足以下至少一个条件的第一个元素

    如果没有这样的元素,则返回 null。

4.3. Mutation observers

每个相同来源窗口代理都有一个突变观察者微任务排队(布尔值),其初始值为false。[HTML]

每个相同来源窗口代理还具有待处理的突变观察者(一个包含零个或多个MutationObserver对象的集合),其初始状态为空。

排队一个突变观察者微任务

  1. 如果外围代理突变观察者微任务已排队为 true,则返回。

  2. 外围代理突变观察者微任务已排队设为 true。

  3. 排队一个微任务用于通知突变观察者

通知突变观察者

  1. 外围代理突变观察者微任务已排队设为 false。

  2. notifySet克隆 外围代理待处理突变观察者

  3. 清空 外围代理待处理突变观察者

  4. signalSet克隆 外围代理信号槽

  5. 清空 外围代理信号槽

  6. 对于 notifySet 中的每个 mo

    1. records克隆 mo记录队列

    2. 清空 mo记录队列

    3. 对于 mo节点列表中的每个 node移除 所有瞬态注册观察者,其 观察者mo,从 node注册观察者列表中。

    4. 如果 records 非空,则 调用 mo回调,参数为 « recordsmo » 和 "report",并以 回调 this 值 mo 调用。

  7. 对于 signalSet 中的每个 slot触发 一个名为 slotchange 的事件,且其 bubbles 属性设为 true,目标为 slot


每个节点有一个注册观察者列表(一个列表,其中包含零个或多个注册观察者),该列表初始为空。

一个注册观察者由一个观察者(一个MutationObserver对象)和选项(一个MutationObserverInit字典)组成。

一个瞬态注册观察者是一个注册观察者,它还包括一个(一个注册观察者)。

临时注册观察者用于追踪某个节点被移除后,其后代中的变更,这样在 subtree节点父节点上设置为 true 时,这些变更不会丢失。

4.3.1. 接口 MutationObserver

[Exposed=Window]
interface MutationObserver {
  constructor(MutationCallback callback);

  undefined observe(Node target, optional MutationObserverInit options = {});
  undefined disconnect();
  sequence<MutationRecord> takeRecords();
};

callback MutationCallback = undefined (sequence<MutationRecord> mutations, MutationObserver observer);

dictionary MutationObserverInit {
  boolean childList = false;
  boolean attributes;
  boolean characterData;
  boolean subtree = false;
  boolean attributeOldValue;
  boolean characterDataOldValue;
  sequence<DOMString> attributeFilter;
};

MutationObserver 对象可以用于观察 节点 的变化。

每个 MutationObserver 对象都有以下关联概念:

observer = new MutationObserver(callback)
构造一个 MutationObserver 对象并将其 回调 设置为 callbackcallback 第一个参数是 MutationRecord 对象的列表,第二个参数是新构造的 MutationObserver 对象。当通过 observe() 方法注册的 节点发生变化时会调用该回调。
observer . observe(target, options)
指示用户代理去观察给定的 target(一个节点),并根据 options(一个对象)中指定的条件报告任何变更。

options 参数允许通过对象成员来设置变更观察选项。可用的对象成员如下:

childList
如果为 true,则要观察 target子节点变动。
attributes
如果为 true,则要观察 target属性变动。如果 attributeOldValueattributeFilter 被指定,可以省略。
characterData
如果为 true,则要观察 target数据变动。如果 characterDataOldValue 被指定,可以省略。
subtree
如果为 true,则不仅要观察 target,还要观察 target后代变动。
attributeOldValue
如果 attributes 为 true 或省略,且需要记录 target 属性在变动前的,则设为 true。
characterDataOldValue
如果 characterData 为 true 或省略,且需要记录 target 数据在变动前的值,则设为 true。
attributeFilter
如果不是所有属性变动都需要观察,且 attributes 为 true 或省略,则设为要过滤的属性本地名(无命名空间)。
observer . disconnect()
停止 observer 观察任何变化。在再次使用 observe() 方法之前,observer回调不会被调用。
observer . takeRecords()
清空记录队列并返回队列的内容。

new MutationObserver(callback) 构造函数步骤为:将thiscallback设置为 callback

observe(target, options) 方法的步骤如下:

  1. 如果 options["attributeOldValue"] 或 options["attributeFilter"] 存在,且 options["attributes"] 不存在,则将 options["attributes"] 设为 true。

  2. 如果 options["characterDataOldValue"] 存在,且 options["characterData"] 不存在,则将 options["characterData"] 设为 true。

  3. 如果 options["childList"]、 options["attributes"]、 options["characterData"] 均不为 true,则抛出 TypeError

  4. 如果 options["attributeOldValue"] 为 true, 且 options["attributes"] 为 false, 则抛出 TypeError

  5. 如果 options["attributeFilter"] 存在,且 options["attributes"] 为 false, 则抛出 TypeError

  6. 如果 options["characterDataOldValue"] 为 true,且 options["characterData"] 为 false, 则抛出 TypeError

  7. 对于 target注册观察者列表中的每个 registered:如果 registeredobserverthis

    1. 对于 this节点列表中的每个 node移除 所有瞬态注册观察者,其 sourceregistered,从 node注册观察者列表中。

    2. registeredoptions 设为 options

  8. 否则:

    1. 追加一个新的注册观察者, 其observerthisoptionsoptions, 到 target注册观察者列表

    2. 追加target 的弱引用到 this节点列表中。

disconnect() 方法的步骤如下:

  1. 对于 this节点列表中的每个 node移除 注册观察者,条件为 this 是其 observer, 从 node注册观察者列表中。

  2. 清空 this记录队列

takeRecords() 方法的步骤如下:

  1. records克隆 this记录队列

  2. 清空 this记录队列

  3. 返回 records

4.3.2. 排队突变记录

要为 targettype 排队一个 突变记录, 带 namenamespaceoldValueaddedNodesremovedNodespreviousSiblingnextSibling

  1. interestedObservers 为一个空的有序映射

  2. nodestarget包含祖先

  3. 对于 nodes 中的每个 node,然后对于 node注册观察者列表中的每个 registered

    1. optionsregisteredoptions

    2. 如果下列条件都不为真

      则:

      1. moregisteredobserver

      2. 如果 interestedObservers[mo] 不存在,则 设置 interestedObservers[mo] 为 null。

      3. 如果 type 是 "attributes" 且 options["attributeOldValue"] 为 true, 或 type 是 "characterData" 且 options["characterDataOldValue"] 为 true, 则 设置 interestedObservers[mo] 为 oldValue

  4. 对于 interestedObservers 中的每个 observermappedOldValue

    1. record 为一个新的 MutationRecord 对象,其 type 设为 typetarget 设为 targetattributeName 设为 nameattributeNamespace 设为 namespaceoldValue 设为 mappedOldValueaddedNodes 设为 addedNodesremovedNodes 设为 removedNodespreviousSibling 设为 previousSiblingnextSibling 设为 nextSibling

    2. 入队 recordobserver记录队列

    3. 追加 observer外围代理待处理突变观察者

  5. 排队一个突变观察者微任务

要为 target,带 addedNodesremovedNodespreviousSiblingnextSibling 排队一个树突变记录

  1. 断言addedNodesremovedNodes 非空

  2. 排队一个突变记录, 类型为 "childList",target 为 target, 参数为 null, null, null, addedNodes, removedNodes, previousSibling, nextSibling

4.3.3. 接口 MutationRecord

[Exposed=Window]
interface MutationRecord {
  readonly attribute DOMString type;
  [SameObject] readonly attribute Node target;
  [SameObject] readonly attribute NodeList addedNodes;
  [SameObject] readonly attribute NodeList removedNodes;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;
  readonly attribute DOMString? attributeName;
  readonly attribute DOMString? attributeNamespace;
  readonly attribute DOMString? oldValue;
};
record . type
返回 "attributes",如果是属性变更; 返回 "characterData",如果是对 CharacterData 节点的变更; 返回 "childList",如果是对结构 节点的变更。
record . target
返回发生变更的节点,具体依赖于 type。对于 "attributes",是属性变更的元素;对于 "characterData",是被更改的 CharacterData 节点;对于 "childList",是发生子节点变更的节点
record . addedNodes
record . removedNodes
分别返回被添加和移除的节点
record . previousSibling
record . nextSibling
分别返回被添加或移除节点前一个下一个兄弟节点;否则为 null。
record . attributeName
返回被更改属性本地名;否则为 null。
record . attributeNamespace
返回被更改属性命名空间;否则为 null。
record . oldValue
返回值依赖于 type。 对于 "attributes",是被更改属性变更前的; 对于 "characterData",是被更改节点变更前的数据; 对于 "childList",为 null。

typetargetaddedNodesremovedNodespreviousSiblingnextSiblingattributeNameattributeNamespaceoldValue 属性必须返回其初始化时的值。

4.4. 接口 Node

[Exposed=Window]
interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2;
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4;
  const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy
  const unsigned short ENTITY_NODE = 6; // legacy
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // legacy
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute USVString baseURI;

  readonly attribute boolean isConnected;
  readonly attribute Document? ownerDocument;
  Node getRootNode(optional GetRootNodeOptions options = {});
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  [SameObject] readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  [CEReactions] attribute DOMString? nodeValue;
  [CEReactions] attribute DOMString? textContent;
  [CEReactions] undefined normalize();

  [CEReactions, NewObject] Node cloneNode(optional boolean subtree = false);
  boolean isEqualNode(Node? otherNode);
  boolean isSameNode(Node? otherNode); // legacy alias of ===

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

  DOMString? lookupPrefix(DOMString? namespace);
  DOMString? lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);

  [CEReactions] Node insertBefore(Node node, Node? child);
  [CEReactions] Node appendChild(Node node);
  [CEReactions] Node replaceChild(Node node, Node child);
  [CEReactions] Node removeChild(Node child);
};

dictionary GetRootNodeOptions {
  boolean composed = false;
};

Node 是所有 节点都在使用的抽象接口。你不能直接获取它的实例。

每个 节点都有关联的 节点文档,在创建时设置,其值为 文档

节点节点文档可以通过 收养(adopt)算法进行更改。

节点获取父节点算法,给定参数 event,会返回该 节点指定插槽,如果 节点已分配的;否则返回该 节点父节点

每个 节点还有一个 注册观察者列表


node . nodeType

返回一个适合 node 类型的数字,如下所示:

Element
Node . ELEMENT_NODE (1)。
Attr
Node . ATTRIBUTE_NODE (2)。
一个排他的 Text 节点
Node . TEXT_NODE (3)。
CDATASection
Node . CDATA_SECTION_NODE (4)。
ProcessingInstruction
Node . PROCESSING_INSTRUCTION_NODE (7)。
Comment
Node . COMMENT_NODE (8)。
Document
Node . DOCUMENT_NODE (9)。
DocumentType
Node . DOCUMENT_TYPE_NODE (10)。
DocumentFragment
Node . DOCUMENT_FRAGMENT_NODE (11)。
node . nodeName

返回一个适合 node 类型的字符串,如下所示:

Element
HTML 大写限定名
Attr
限定名
一个排他的 Text 节点
"#text"。
CDATASection
"#cdata-section"。
ProcessingInstruction
目标
Comment
"#comment"。
Document
"#document"。
DocumentType
名称
DocumentFragment
"#document-fragment"。

nodeType getter 的步骤是返回第一个匹配的语句,具体取决于此对象实现的接口:

Element
ELEMENT_NODE (1)
Attr
ATTRIBUTE_NODE (2);
一个排他的 Text 节点
TEXT_NODE (3);
CDATASection
CDATA_SECTION_NODE (4);
ProcessingInstruction
PROCESSING_INSTRUCTION_NODE (7);
Comment
COMMENT_NODE (8);
Document
DOCUMENT_NODE (9);
DocumentType
DOCUMENT_TYPE_NODE (10);
DocumentFragment
DOCUMENT_FRAGMENT_NODE (11).

nodeName getter 的步骤是返回第一个匹配的语句,具体取决于此对象实现的接口:

Element
HTML 大写限定名
Attr
限定名
一个排他的 Text 节点
"#text"。
CDATASection
"#cdata-section"。
ProcessingInstruction
目标
Comment
"#comment"。
Document
"#document"。
DocumentType
名称
DocumentFragment
"#document-fragment"。

node . baseURI
返回 node节点文档文档基本 URL

baseURI getter 的步骤是返回此对象节点文档文档基本 URL,并进行序列化


node . isConnected

如果 node已连接的,则返回 true;否则返回 false。

node . ownerDocument
返回节点文档。 对于文档,返回 null。
node . getRootNode()
返回 node根节点
node . getRootNode({ composed:true })
返回 node包含阴影的根节点
node . parentNode
返回父节点
node . parentElement
返回父元素
node . hasChildNodes()
返回 node 是否有子节点
node . childNodes
返回子节点
node . firstChild
返回第一个子节点
node . lastChild
返回最后一个子节点
node . previousSibling
返回前一个兄弟节点
node . nextSibling
返回下一个兄弟节点

isConnected 的 getter 步骤是:如果 this已连接,则返回 true;否则返回 false。

ownerDocument 的 getter 步骤是:如果 this文档,则返回 null;否则返回 this节点文档

文档节点文档就是该 文档本身。所有 节点始终拥有一个 节点文档

getRootNode(options) 方法的步骤是:如果 options["composed"] 为 true,则返回此对象包含阴影的根节点;否则返回此对象根节点

parentNode getter 的步骤是返回此对象父节点

parentElement getter 的步骤是返回此对象父元素

hasChildNodes() 方法的步骤是:如果此对象子节点,则返回 true;否则返回 false。

childNodes getter 的步骤是返回一个以此对象为根且仅匹配子节点NodeList

firstChild getter 的步骤是返回此对象第一个子节点

lastChild getter 的步骤是返回此对象最后一个子节点

previousSibling getter 的步骤是返回此对象前一个兄弟节点

nextSibling getter 的步骤是返回此对象下一个兄弟节点


nodeValue getter 的步骤是返回以下内容,具体取决于此对象实现的接口:

Attr
此对象
CharacterData
此对象数据
其他情况
Null。

nodeValue setter 的步骤是,如果给定值为 null,则视为空字符串,然后执行以下描述的操作,具体取决于此对象实现的接口:

Attr

使用此对象和给定值设置现有特性值

CharacterData

用 0、this长度 和给定值,替换数据

其他情况

不执行任何操作。

使用节点 node 获取文本内容的步骤是返回以下内容,具体取决于 node 实现的接口:

DocumentFragment
Element
node后代文本内容
Attr
node
CharacterData
node数据
其他情况
Null。

The textContent getter 步骤为:返回运行 获取文本内容 并以 this 作为参数的结果。

要在一个 node parent 内对字符串 string 执行 string replace all,请运行下列步骤:

  1. node 为 null。

  2. 如果 string 不是空字符串,则将 node 设为一个新的 Text node,其 datastring,且其 node documentparentnode document

  3. 替换全部:在 parent 内用 node 替换全部内容。

要使用一个 node node 和一个字符串 value设置文本内容,按下述定义执行,基于 node 实现的接口(switch on the interface node implements)进行分支:

DocumentFragment
Element

对字符串执行全部替换:在 node 内用 value 替换全部。

Attr

调用 设置已有属性值,参数为 nodevalue

CharacterData

用 0、node长度value 替换数据

Otherwise

不执行任何操作。

The textContent setter 的步骤是:如果给定的值为 null,则将其视为一个空字符串,然后用 设置文本内容 算法,以 this 和该给定值作为参数运行。


node . normalize()
移除独立 Text 节点,并把剩余连续的独立 Text 节点数据拼接到它们中的第一个节点

normalize() 方法的步骤为:对 this 的每一个独占 Text 节点后代 node,执行以下步骤:

  1. lengthnode长度

  2. 如果 length 为 0,则移除 node 并进入下一个 独占 Text 节点(如有)。

  3. datanode连续独占 Text 节点(不包括自身)中、按树序数据,并连接之。

  4. length、0 和 data 替换 node 的数据。

  5. currentNodenode下一个兄弟节点

  6. currentNode独占 Text 节点时,执行:

    1. 对于所有 start nodecurrentNodelive range:将其start offset加上 length 并将 start node 设为 node

    2. 对于所有 end nodecurrentNodelive range:将其end offset加上 length 并将 end node 设为 node

    3. 对于所有 start nodecurrentNode父节点start offsetcurrentNode索引live range:将其 start node 设为 node,其 start offset设为 length

    4. 对于所有 end nodecurrentNode父节点end offsetcurrentNode索引live range:将其 end node 设为 node,其 end offset设为 length

    5. currentNode长度加到 length

    6. currentNode 设为其下一个兄弟节点

  7. 树序移除 node连续独占 Text 节点(不包括自身)。


node . cloneNode([subtree = false])
返回 node 的一个副本。如果 subtree 为 true,则副本也包括 node后代
node . isEqualNode(otherNode)
判断 nodeotherNode 的属性是否相同。
规范可为全部或部分节点定义克隆步骤。该算法传入 nodecopysubtree,如节点克隆算法所示。

HTML 为若干元素(如 inputscripttemplate) 定义了 克隆步骤。SVG 应为其 script 元素也做同样的事,但尚未定义。

克隆节点,给定 节点 node, 可选 文档 document(默认值为 node节点文档),布尔值 subtree(默认 false), 节点或 null parent(默认 null),以及 null 或 CustomElementRegistry 对象 fallbackRegistry(默认 null):

  1. 断言node 不是 文档,或 nodedocument

  2. copy克隆单个节点得到的结果,参数为 nodedocumentfallbackRegistry

  3. 执行 克隆步骤,在 其它相关规范中,为 node 定义,并传递 nodecopysubtree

  4. 如果 parent 非 null,则 添加 copyparent

  5. 如果 subtree 为 true,则遍历 node 的每个 子节点,按 树顺序克隆节点,参数为 childdocument 设为 documentsubtree 设为 subtreeparent 设为 copyfallbackRegistry 设为 fallbackRegistry

  6. 如果 node元素nodeshadow host,且 nodeshadow rootclonable 为 true:

    1. 断言copy 不是 shadow host

    2. shadowRootRegistrynodeshadow rootcustom element registry

    3. 如果 shadowRootRegistry 是全局 custom element registry,则设 shadowRootRegistrydocumenteffective global custom element registry

    4. 附加 shadow root,参数为 copynodeshadow rootmode、true、nodeshadow rootserializablenodeshadow rootdelegates focusnodeshadow rootslot assignment,以及 shadowRootRegistry

    5. copyshadow rootdeclarativenodeshadow rootdeclarative

    6. 遍历 nodeshadow root子节点,按 树顺序克隆节点,参数为 childdocument 设为 documentsubtree 设为 subtreeparent 设为 copyshadow root

      此处特意不传递 fallbackRegistry 参数。

  7. 返回 copy

克隆单个节点,给定 节点 node文档 document,以及 null 或 CustomElementRegistry 对象 fallbackRegistry

  1. copy 为 null。

  2. 如果 node元素

    1. registrynodecustom element registry

    2. 如果 registry 为 null,则把 registry 设为 fallbackRegistry

    3. 如果 registry 是全局 custom element registry,则设 registrydocumenteffective global custom element registry

    4. copy创建元素后的结果,参数为 documentnodelocal namenodenamespacenodenamespace prefixnodeis、false 以及 registry

    5. 遍历 node属性列表中的每个 attribute

      1. copyAttribute克隆单个节点的结果,参数为 attributedocument 和 null。

      2. 添加 copyAttributecopy

  3. 否则,令 copy 为一个 节点,该节点 实现node 相同的接口,并切换接口 node 实现时符合下列额外要求:

    Document
    1. copy编码内容类型URL来源类型模式允许声明式 shadow rootnode 保持一致。

    2. 如果 nodecustom element registryis scoped 为 true,则令 copycustom element registrynodecustom element registry 保持一致。

    DocumentType

    copynamepublic IDsystem ID 赋值为 node 的对应值。

    Attr

    copynamespacenamespace prefixlocal namevalue 赋值为 node 的对应值。

    Text
    Comment

    copydata 赋值为 node 的对应值。

    ProcessingInstruction

    copytargetdata 赋值为 node 的对应值。

    否则

    无操作。

  4. 断言copy 是一个 节点

  5. 如果 node文档,则把 document 设为 copy

  6. copy节点文档 设为 document

  7. 返回 copy

cloneNode(subtree) 方法步骤:

  1. 如果 thisshadow root,则抛出 "NotSupportedError" DOMException

  2. 返回以 克隆节点 调用 this,且 subtree 设为 subtree 的结果。

节点 A 等于(equals) 节点 B,需满足以下所有条件:

isEqualNode(otherNode) 方法步骤:如果 otherNode 非 null 且 this 等于 otherNode,则返回 true;否则返回 false。

isSameNode(otherNode) 方法步骤:如果 otherNodethis,则返回 true;否则返回 false。


node . compareDocumentPosition(other)
返回一个位掩码,指示 other 相对于 node 的位置。可以设置以下这些位:
Node . DOCUMENT_POSITION_DISCONNECTED (1)
nodeother 不在同一中时设置。
Node . DOCUMENT_POSITION_PRECEDING (2)
other 先于 node 时设置。
Node . DOCUMENT_POSITION_FOLLOWING (4)
other 后于 node 时设置。
Node . DOCUMENT_POSITION_CONTAINS (8)
othernode祖先时设置。
Node . DOCUMENT_POSITION_CONTAINED_BY (16,十六进制下为 10)
othernode后代时设置。
node . contains(other)
如果 othernode包含后代,则返回 true;否则返回 false。

以下是compareDocumentPosition()返回的掩码常量:

方法compareDocumentPosition(other)的步骤如下:

  1. 如果 thisother,则返回零。

  2. node1other,令 node2this

  3. attr1attr2 为 null。

  4. 如果 node1 是一个 attribute,则将 attr1 设为 node1,并将 node1 设为 attr1element

  5. 如果 node2 是一个 attribute

    1. attr2 设为 node2,并将 node2 设为 attr2element

    2. 如果 attr1node1 非空,且 node2node1

      1. 对于 node2attribute list 中的每个 attr

        1. 如果 attr equals attr1,则返回将 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFICDOCUMENT_POSITION_PRECEDING 相加的结果。

        2. 如果 attr equals attr2,则返回将 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFICDOCUMENT_POSITION_FOLLOWING 相加的结果。

  6. 如果 node1node2 为 null,或 node1root 不是 node2root,则返回将 DOCUMENT_POSITION_DISCONNECTEDDOCUMENT_POSITION_IMPLEMENTATION_SPECIFICDOCUMENT_POSITION_PRECEDINGDOCUMENT_POSITION_FOLLOWING(二者之一)相加的结果,并且附带这些值须保持一致的约束。

    通常通过指针比较来决定返回 DOCUMENT_POSITION_PRECEDING 还是 DOCUMENT_POSITION_FOLLOWING。在 JavaScript 实现中,可以使用缓存的 Math.random() 值来实现。

  7. 如果 node1node2ancestorattr1 为 null,或 node1node2 相同且 attr2 非空,则返回将 DOCUMENT_POSITION_CONTAINSDOCUMENT_POSITION_PRECEDING 相加的结果。

  8. 如果 node1node2descendantattr2 为 null,或 node1node2 相同且 attr1 非空,则返回将 DOCUMENT_POSITION_CONTAINED_BYDOCUMENT_POSITION_FOLLOWING 相加的结果。

  9. 如果 node1 在树序上 preceding node2,则返回 DOCUMENT_POSITION_PRECEDING

    由于在此算法中对 attributes 的处理方式,这会导致一个 nodeattributes 被算作是 preceding,处于该 nodechildren 之前,尽管 attributes 并未 participating 在同一 tree 中。

  10. 返回 DOCUMENT_POSITION_FOLLOWING

contains(other) 方法的步骤是:如果 other此对象包含后代,则返回 true;否则返回 false(包括当 other 为 null 时)。


要为一个使用namespaceelement 定位命名空间前缀,请执行以下步骤:

  1. 如果element命名空间namespace,且其命名空间前缀非空,则返回其命名空间前缀

  2. 如果element具有一个属性,其命名空间前缀是"xmlns"且namespace,则返回element的第一个此类属性本地名称

  3. 如果 element父元素不为 null,则返回在该元素上使用 namespace 运行定位命名空间前缀的结果。

  4. 返回 null。

要为一个node使用prefix 定位命名空间,请根据node 实现的接口进行切换:

Element
  1. 如果prefix是"xml",则返回XML 命名空间

  2. 如果prefix是"xmlns",则返回XMLNS 命名空间

  3. 如果其命名空间非空,且其命名空间前缀prefix,则返回命名空间

  4. 如果它具有一个属性,该属性的命名空间XMLNS 命名空间命名空间前缀为"xmlns",且本地名称prefix,或者如果prefix为 null,且它具有一个属性,其命名空间XMLNS 命名空间命名空间前缀为 null,且本地名称为"xmlns",则返回其(如果值不是空字符串),否则返回 null。

  5. 如果其父元素为 null,则返回 null。

  6. 返回在其父元素上使用prefix运行定位命名空间的结果。

Document
  1. 如果其文档元素为 null,则返回 null。

  2. 返回在其文档元素上使用prefix运行定位命名空间的结果。

DocumentType
DocumentFragment

返回 null。

Attr
  1. 如果其元素为 null,则返回 null。

  2. 返回在其元素上使用prefix运行定位命名空间的结果。

否则
  1. 如果其父元素为 null,则返回 null。

  2. 返回在其父元素上使用prefix运行定位命名空间的结果。

方法lookupPrefix(namespace)的步骤如下:

  1. 如果 namespace 为 null 或空字符串,则返回 null。

  2. 根据此对象实现的接口进行切换:

    Element

    返回为此对象使用 namespace 定位命名空间前缀的结果。

    Document
    1. 如果此对象文档元素为 null,则返回 null。

    2. 返回为此对象文档元素使用 namespace 定位命名空间前缀的结果。

    DocumentType
    DocumentFragment

    返回 null。

    Attr
    1. 如果此对象元素为 null,则返回 null。

    2. 返回为此对象元素使用 namespace 定位命名空间前缀的结果。

    其他情况
    1. 如果此对象父元素为 null,则返回 null。

    2. 返回为此对象父元素使用 namespace 定位命名空间前缀的结果。

方法lookupNamespaceURI(prefix)的步骤如下:

  1. 如果 prefix 是空字符串,则将其设置为 null。

  2. 返回使用 prefix此对象定位命名空间的结果。

方法isDefaultNamespace(namespace)的步骤如下:

  1. 如果 namespace 是空字符串,则将其设置为 null。

  2. defaultNamespace 为对此对象使用 null 定位命名空间的结果。

  3. 如果 defaultNamespacenamespace 相同,则返回 true;否则返回 false。


insertBefore(node, child) 方法的步骤是返回将 node 预插入此对象child 之前的结果。

appendChild(node) 方法的步骤是返回将 node 追加此对象的结果。

replaceChild(node, child) 方法的步骤是返回在此对象内用 node 替换 child 的结果。

removeChild(child) 方法的步骤是返回从此对象预移除 child 的结果。


对于节点 root具有限定名 qualifiedName 的元素列表是由以下算法返回的 HTMLCollection

  1. 如果 qualifiedName 是 U+002A (*),则返回一个以 root 为根的 HTMLCollection,其过滤器仅匹配后代元素

  2. 否则,如果 root节点文档HTML 文档, 则返回一个以 root 为根的 HTMLCollection,其过滤器匹配以下后代元素

  3. 否则,返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素,这些元素的限定名qualifiedName

当使用相同参数调用时,并且只要 root节点文档类型没有改变,就可以返回与先前调用返回的相同的 HTMLCollection 对象。

对于节点 root具有命名空间 namespace 和本地名称 localName 的元素列表是由以下算法返回的 HTMLCollection

  1. 如果 namespace 是空字符串,则将其设置为 null。

  2. 如果 namespacelocalName 都是 U+002A (*),则返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素

  3. 如果 namespace 是 U+002A (*),则返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素,这些元素的本地名称localName

  4. 如果 localName 是 U+002A (*),则返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素,这些元素的命名空间namespace

  5. 返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素,这些元素的命名空间namespace本地名称localName

当使用相同参数调用时,可以返回与先前调用返回的相同的 HTMLCollection 对象。

对于节点 root具有类名 classNames 的元素列表是由以下算法返回的 HTMLCollection

  1. classes 为对 classNames 运行有序集合解析器的结果。
  2. 如果 classes 是空集,则返回一个空的 HTMLCollection
  3. 返回一个以 root 为根的 HTMLCollection,其过滤器匹配后代元素,这些元素在 classes 中拥有其所有的

    如果 root节点文档模式是“quirks”,则的比较必须以ASCII 不区分大小写的方式进行;否则以完全相同的方式进行。

当使用相同参数调用时,可以返回与先前调用返回的相同的 HTMLCollection 对象。

4.5. 接口 Document

[Exposed=Window]
interface Document : Node {
  constructor();

  [SameObject] readonly attribute DOMImplementation implementation;
  readonly attribute USVString URL;
  readonly attribute USVString documentURI;
  readonly attribute DOMString compatMode;
  readonly attribute DOMString characterSet;
  readonly attribute DOMString charset; // legacy alias of .characterSet
  readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
  readonly attribute DOMString contentType;

  readonly attribute DocumentType? doctype;
  readonly attribute Element? documentElement;
  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions, NewObject] Element createElement(DOMString localName, optional (DOMString or ElementCreationOptions) options = {});
  [CEReactions, NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional (DOMString or ElementCreationOptions) options = {});
  [NewObject] DocumentFragment createDocumentFragment();
  [NewObject] Text createTextNode(DOMString data);
  [NewObject] CDATASection createCDATASection(DOMString data);
  [NewObject] Comment createComment(DOMString data);
  [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);

  [CEReactions, NewObject] Node importNode(Node node, optional (boolean or ImportNodeOptions) options = false);
  [CEReactions] Node adoptNode(Node node);

  [NewObject] Attr createAttribute(DOMString localName);
  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);

  [NewObject] Event createEvent(DOMString interface); // legacy

  [NewObject] Range createRange();

  // NodeFilter.SHOW_ALL = 0xFFFFFFFF
  [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
  [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
};

[Exposed=Window]
interface XMLDocument : Document {};

dictionary ElementCreationOptions {
  CustomElementRegistry? customElementRegistry;
  DOMString is;
};

dictionary ImportNodeOptions {
  CustomElementRegistry customElementRegistry;
  boolean selfOnly = false;
};

Document 节点简称为 文档

文档节点文档就是它自身。

每个 文档都关联 编码(一个编码), 内容类型(字符串), URL(一个 URL), 来源(一个 来源(origin)), 类型("xml" 或 "html"), 模式("no-quirks"、"quirks" 或 "limited-quirks"), 允许声明式 Shadow Root(布尔值), 以及 自定义元素注册表(null 或 CustomElementRegistry 对象)。 [ENCODING] [URL] [HTML]

除非另有说明,文档编码utf-8 编码内容类型为 "application/xml", URL 为 "about:blank", 来源不透明来源类型为 "xml", 模式为 "no-quirks", 允许声明式 Shadow Root 为 false, 自定义元素注册表为 null。

文档如果 类型为 "xml",被称为 XML 文档;否则为 HTML 文档。 文档是 HTML 文档 还是 XML 文档 会影响某些 API 的行为。

文档如果 模式为 "no-quirks",则称为 无怪癖模式(no-quirks mode); 如果 模式为 "quirks",则称为 怪癖模式(quirks mode); 如果 模式为 "limited-quirks",则称为 有限怪癖模式(limited-quirks mode)

模式只有在由 文档通过 HTML 解析器创建时,依据 DOCTYPE 字符串的存在、缺失或取值,以及新 浏览上下文(初始为 "about:blank"),才会被更改默认值。[HTML]

无怪癖模式原称为 "标准模式",有限怪癖模式原称 "几乎标准模式"。现已改名,因为详细规范由标准定义。(且 Ian Hickson 基于原名荒谬,否决了原名。)

文档获取父节点算法,给定 event,若 eventtype 属性值为 "load" 或 文档没有 浏览上下文,则返回 null;否则返回 文档关联全局对象


document = new Document()
返回一个新的 文档
document . implementation
返回 documentDOMImplementation 对象。
document . URL
document . documentURI
返回 documentURL
document . compatMode
如果 document模式为 "quirks",则返回字符串 "BackCompat",否则返回 "CSS1Compat"。
document . characterSet
返回 document编码
document . contentType
返回 document内容类型

new Document() 构造器步骤为:将 this来源(origin) 设为 来源, 即 当前全局对象关联 Document 的来源。[HTML]

createDocument() 不同,此构造器不会返回 XMLDocument 对象,而只返回 文档Document 对象)。

implementation 的 getter 步骤是:返回与 this 关联的 DOMImplementation 对象。

URLdocumentURI 的 getter 步骤是:返回 thisURL序列化

compatMode 的 getter 步骤是:如果 this模式是 "quirks",则返回 "BackCompat";否则返回 "CSS1Compat"。

characterSetcharsetinputEncoding 的 getter 步骤是:返回 this编码名称

contentType 的 getter 步骤是:返回 this内容类型


document . doctype
返回 文档类型节点,如果不存在则返回 null。
document . documentElement
返回 文档元素
collection = document . getElementsByTagName(qualifiedName)

如果 qualifiedName 是 "*",则返回所有 后代 元素HTMLCollection

否则,返回所有 后代 元素HTMLCollection,这些元素的 限定名等于 qualifiedName。(在 HTML 命名空间内的 HTML 文档将不区分大小写匹配 元素。)

collection = document . getElementsByTagNameNS(namespace, localName)

如果 namespacelocalName 都是 "*",返回所有 后代 元素HTMLCollection

如果只有 namespace 是 "*",返回所有 后代 元素HTMLCollection,这些元素的 本地名localName

如果只有 localName 是 "*",返回所有 后代 元素HTMLCollection,这些元素的 命名空间namespace

否则,返回所有 后代 元素HTMLCollection,这些元素的 命名空间namespace本地名localName

collection = document . getElementsByClassName(classNames)
collection = element . getElementsByClassName(classNames)

返回在该对象上调用该方法(一个 文档元素)内具有所有 classNames 指定类名的 元素HTMLCollectionclassNames 参数被解释为用空格分隔的类名列表。

doctype getter 的步骤是返回此对象中作为文档类型子节点;否则返回 null。

documentElement getter 的步骤是返回此对象文档元素

getElementsByTagName(qualifiedName) 方法的步骤是返回此对象具有限定名 qualifiedName 的元素列表

因此,在 HTML 文档中,document.getElementsByTagName("FOO") 将匹配不在HTML 命名空间中的 <FOO> 元素,以及在HTML 命名空间中的 <foo> 元素,但不匹配在HTML 命名空间中的 <FOO> 元素。

getElementsByTagNameNS(namespace, localName) 方法的步骤是返回此对象具有命名空间 namespace 和本地名称 localName 的元素列表

getElementsByClassName(classNames) 方法的步骤是返回此对象具有类名 classNames 的元素列表

给出以下的XHTML片段:
<div id="example">
  <p id="p1" class="aaa bbb"/>
  <p id="p2" class="aaa ccc"/>
  <p id="p3" class="bbb ccc"/>
</div>

调用document.getElementById("example").getElementsByClassName("aaa")将返回一个包含两个段落p1p2HTMLCollection

调用getElementsByClassName("ccc bbb")将只返回一个节点,即p3。调用document.getElementById("example").getElementsByClassName("bbb ccc ")将返回相同的内容。

调用getElementsByClassName("aaa,bbb")将不会返回任何节点;上面的元素中没有一个属于aaa,bbb类。


element = document . createElement(localName [, options])

返回一个 元素,其 本地名localName(如果 documentHTML 文档,则 localName 会被转为小写)。该 元素命名空间为:当 documentHTML 文档document内容类型为 "application/xhtml+xml" 时,则为 HTML 命名空间;否则为 null。

如果指定,optionscustomElementRegistry 可用于设置 CustomElementRegistry

如果指定,optionsis 可用于创建 定制内置元素

如果 localName 不是 有效的元素本地名,将抛出 "InvalidCharacterError" DOMException

如果同时提供了 optionscustomElementRegistryis,将抛出 "NotSupportedError" DOMException

element = document . createElementNS(namespace, qualifiedName [, options])

返回一个 元素,其 命名空间namespace。其 命名空间前缀qualifiedName 中 U+003A (:) 之前的内容,或 null。其 本地名qualifiedName 中 U+003A (:) 之后的内容,或 qualifiedName 本身。

如果指定,optionscustomElementRegistry 可用于设置 CustomElementRegistry

如果指定,optionsis 可用于创建 定制内置元素

如果 qualifiedName 不是(可能带前缀的)有效的元素本地名,将抛出 "InvalidCharacterError" DOMException

若以下任意条件为真,将抛出 "NamespaceError" DOMException

如果同时提供了 optionscustomElementRegistryis,将抛出 "NotSupportedError" DOMException

documentFragment = document . createDocumentFragment()
返回一个 DocumentFragment 节点
text = document . createTextNode(data)
返回一个 Text 节点,其 数据data
text = document . createCDATASection(data)
返回一个 CDATASection 节点,其 数据data
comment = document . createComment(data)
返回一个 Comment 节点,其 数据data
processingInstruction = document . createProcessingInstruction(target, data)
返回一个 ProcessingInstruction 节点,其 targettarget数据data。如果 target 不符合 Name 产生式,将抛出 "InvalidCharacterError" DOMException。如果 data 包含 "?>",将抛出 "InvalidCharacterError" DOMException

任何 namenamespace元素接口都是 Element,除非另有说明。

例如,HTML 标准将定义对于 htmlHTML 命名空间,使用 HTMLHtmlElement 接口。[HTML]

createElement(localName, options) 方法的步骤如下:

  1. 如果 localName 不是一个有效的元素本地名称,则 抛出一个“InvalidCharacterErrorDOMException

  2. 如果此对象是一个HTML 文档,则将 localName 设置为 localNameASCII 小写形式。

  3. registryis 为给定 options此对象扁平化元素创建选项的结果。

  4. 如果此对象是一个HTML 文档或者此对象内容类型是“application/xhtml+xml”,则设 namespaceHTML 命名空间;否则为 null。

  5. 返回给定此对象localNamenamespace、null、is、true 和 registry 创建元素的结果。

内部 createElementNS 步骤,给定 documentnamespacequalifiedNameoptions,如下所示:

  1. 令 (namespace, prefix, localName) 为给定 "element" 验证并提取 namespacequalifiedName 的结果。

  2. registryis 为给定 options此对象扁平化元素创建选项的结果。

  3. 返回给定 documentlocalNamenamespaceprefixis、true 和 registry 创建元素的结果。

createElementNS(namespace, qualifiedName, options) 方法的步骤是返回运行内部 createElementNS 步骤的结果,给定此对象namespacequalifiedNameoptions

展平元素创建选项,给定一个字符串或 ElementCreationOptions 字典 options 和一个 document document

  1. registry 为使用 document 查找自定义元素注册表 的结果。

  2. is 为 null。

  3. 如果 options 是一个字典:

    1. 如果 options["is"] 存在,则将 is 设为其值。

    2. 如果 options["customElementRegistry"] 存在

      1. 如果 is 非 null,则抛出一个 "NotSupportedError" DOMException

      2. registry 设为 options["customElementRegistry"]。

    3. 如果 registry 非 null,且 registry是否作用域限定为 false,并且 registry 不是 document自定义元素注册表,则抛出 "NotSupportedError" DOMException

  4. 返回 registryis

createElement()createElementNS()options 参数允许为字符串,以保证网页兼容性。

createDocumentFragment() 方法步骤为:返回一个新的 DocumentFragment 节点,其 节点文档this

createTextNode(data) 方法步骤为:返回一个新的 Text 节点,其 数据data节点文档this

createCDATASection(data) 方法步骤:

  1. 如果 thisHTML 文档,则 抛出NotSupportedErrorDOMException

  2. 如果 data 包含字符串 "]]>",则 抛出InvalidCharacterErrorDOMException

  3. 返回一个新的 CDATASection 节点,其 数据设为 data节点文档设为 this

createComment(data) 方法步骤为:返回一个新的 Comment 节点,其 数据data节点文档this

createProcessingInstruction(target, data) 方法步骤:

  1. 如果 target 不符合 Name 产生式,则 抛出InvalidCharacterErrorDOMException
  2. 如果 data 包含字符串 "?>",则 抛出InvalidCharacterErrorDOMException
  3. 返回一个新的 ProcessingInstruction 节点targettarget数据data节点文档this

clone = document . importNode(node [, options = false])

返回 node 的副本。如果 options 是 true 或 options 是一个其 selfOnly 为 false 的字典,则副本也包含 node后代

optionscustomElementRegistry 可用于设置没有的元素的 CustomElementRegistry

如果 node文档shadow root,抛出 “NotSupportedErrorDOMException

node = document . adoptNode(node)

从另一个 文档中移动 node 并返回。

如果 node文档,抛出 “NotSupportedErrorDOMException;或者如果 nodeshadow root,抛出 “HierarchyRequestErrorDOMException

importNode(node, options) 方法步骤:

  1. 如果 node文档shadow root,则 抛出NotSupportedErrorDOMException

  2. subtree 为 false。

  3. registry 为 null。

  4. 如果 options 是布尔值,则设 subtreeoptions

  5. 否则:

    1. subtreeoptions["selfOnly"] 的反值。

    2. 如果 options["customElementRegistry"]存在,则设 registry 为其值。

    3. 如果 registryis scoped 为 false 且 registry 不是 thiscustom element registry,则 抛出NotSupportedErrorDOMException

  6. 如果 registry 为 null,则令 registry查找自定义元素注册表(参数 this)。

  7. 返回以 克隆节点调用 nodedocument 设为 thissubtree 设为 subtreefallbackRegistry 设为 registry 的结果。

规范可以为所有或部分 节点定义 adopting steps。该算法以 nodeoldDocument 作为参数,如 adopt 算法所示。

收养一个 节点 nodedocument document

  1. oldDocumentnode节点文档

  2. 如果 node父节点 非 null,则 移除 node

  3. 如果 document 不是 oldDocument

    1. 遍历 node包含 shadow 的所有后代(以 包含 shadow 的树顺序):

      1. inclusiveDescendant节点文档设为 document

      2. 如果 inclusiveDescendantshadow root,并且以下条件之一为真:

        则将 inclusiveDescendantcustom element registry 设为 documenteffective global custom element registry

      3. 否则,若 inclusiveDescendant元素

        1. inclusiveDescendant属性列表中每个 属性节点文档设为 document

        2. 如果 inclusiveDescendantcustom element registry 为 null 或 inclusiveDescendantcustom element registryis scoped 为 false,则将 inclusiveDescendantcustom element registry 设为 documenteffective global custom element registry

    2. 遍历 node包含 shadow 的所有后代且是 自定义元素的,按 包含 shadow 的树顺序入列自定义元素回调 reaction,参数为 inclusiveDescendant、回调名 “adoptedCallback” 和 « oldDocument, document »。

    3. 遍历 node包含 shadow 的所有后代(按 包含 shadow 的树顺序):执行 adopting steps,参数为 inclusiveDescendantoldDocument

adoptNode(node) 方法步骤:

  1. 如果 node文档,则 抛出NotSupportedErrorDOMException

  2. 如果 nodeshadow root,则 抛出HierarchyRequestErrorDOMException

  3. 如果 nodeDocumentFragment 节点并且 host 非 null,则返回。

  4. 收养 nodethis

  5. 返回 node


Null 或一个 CustomElementRegistry 对象 registry 当其非 null 且 registryis scoped 为 false 时,为全局 custom element registry

文档 documenteffective global custom element registry 如下:

  1. 如果 documentcustom element registry 为全局 custom element registry,则返回 documentcustom element registry

  2. 返回 null。


createAttribute(localName) 方法步骤:

  1. 如果 localName 不是 有效属性本地名,则 抛出InvalidCharacterErrorDOMException

  2. 如果 thisHTML 文档,则将 localName 转为 ASCII 小写
  3. 返回一个新的 属性,其 本地名localName节点文档this

createAttributeNS(namespace, qualifiedName) 方法步骤:

  1. 令 (namespace, prefix, localName) 为 校验及提取 namespacequalifiedName(属性类型)后的结果。

  2. 返回一个新的 属性,其 命名空间namespace命名空间前缀prefix本地名localName节点文档this


createEvent(interface) 方法步骤:

  1. constructor 为 null。

  2. interface 为任一第一列字符串(ASCII不区分大小写),则将 constructor 设为同列第二个接口:

    字符串 接口 备注
    "beforeunloadevent" BeforeUnloadEvent [HTML]
    "compositionevent" CompositionEvent [UIEVENTS]
    "customevent" CustomEvent
    "devicemotionevent" DeviceMotionEvent [DEVICE-ORIENTATION]
    "deviceorientationevent" DeviceOrientationEvent
    "dragevent" DragEvent [HTML]
    "event" Event
    "events"
    "focusevent" FocusEvent [UIEVENTS]
    "hashchangeevent" HashChangeEvent [HTML]
    "htmlevents" Event
    "keyboardevent" KeyboardEvent [UIEVENTS]
    "messageevent" MessageEvent [HTML]
    "mouseevent" MouseEvent [UIEVENTS]
    "mouseevents"
    "storageevent" StorageEvent [HTML]
    "svgevents" Event
    "textevent" TextEvent [UIEVENTS]
    "touchevent" TouchEvent [TOUCH-EVENTS]
    "uievent" UIEvent [UIEVENTS]
    "uievents"
  3. 如果 constructor 为 null,则 抛出NotSupportedErrorDOMException

  4. 如果 constructor 指定的接口未在 关联全局对象(此 this)上暴露,则 抛出NotSupportedErrorDOMException

    通常用户代理在某些配置下禁用触摸事件支持,届时此条款会对 TouchEvent 触发。

  5. event创建事件(参数为 constructor)的结果。

  6. 初始化 eventtype 属性为空字符串。

  7. 初始化 eventtimeStamp 属性为调用 当前高精度时间(参数为 this关联全局对象)的结果。

  8. 初始化 eventisTrusted 属性为 false。

  9. 取消设置 eventinitialized flag

  10. 返回 event

Event 构造器应当优先用。


createRange() 方法步骤为:返回一个新的 live range,其 this 和 0 作为 startend

Range() 构造器也可使用。


createNodeIterator(root, whatToShow, filter) 方法步骤:

  1. iterator 为新的 NodeIterator 对象。

  2. iteratorrootiteratorreference 设为 root

  3. iteratorpointer before reference 设为 true。

  4. iteratorwhatToShow 设为 whatToShow

  5. iteratorfilter 设为 filter

  6. 返回 iterator

createTreeWalker(root, whatToShow, filter) 方法步骤:

  1. walker 为新的 TreeWalker 对象。

  2. walkerrootwalkercurrent 设为 root

  3. walkerwhatToShow 设为 whatToShow

  4. walkerfilter 设为 filter

  5. 返回 walker

4.5.1.接口 DOMImplementation

用户代理在创建 document 时,必须创建一个 DOMImplementation 对象,并将其与该 document 关联。

[Exposed=Window]
interface DOMImplementation {
  [NewObject] DocumentType createDocumentType(DOMString name, DOMString publicId, DOMString systemId);
  [NewObject] XMLDocument createDocument(DOMString? namespace, [LegacyNullToEmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
  [NewObject] Document createHTMLDocument(optional DOMString title);

  boolean hasFeature(); // useless; always returns true
};
doctype = document . implementation . createDocumentType(qualifiedName, publicId, systemId)
返回一个具有给定 namepublicIdsystemId文档类型

如果 name 不是一个有效的文档类型名称,则会抛出“InvalidCharacterErrorDOMException

doc = document . implementation . createDocument(namespace, qualifiedName [, doctype = null])
返回一个 XMLDocument,其文档元素本地名称qualifiedName命名空间namespace(除非 qualifiedName 为空字符串),并且如果给定了 doctype,则将其作为其文档类型

当使用 namespacequalifiedName 调用时,此方法会抛出与 createElementNS() 方法相同的异常。

doc = document . implementation . createHTMLDocument([title])
返回一个文档,其中已构建了一个基本的,包括一个 title 元素,除非省略了 title 参数。

createDocumentType(name, publicId, systemId) 方法的步骤如下:

  1. 如果 name 不是有效的 doctype 名称,则抛出一个 "InvalidCharacterError" DOMException

  2. 返回一个新的doctype,其 namenamepublic IDpublicIdsystem IDsystemId,并将其 节点文档 设置为 document(即 this 所关联文档)。

createDocument(namespace, qualifiedName, doctype) 方法的步骤如下:

  1. document 为一个新的 XMLDocument

  2. element 为 null。

  3. 如果 qualifiedName 不是空字符串,则将 element 设为运行内部 createElementNS 步骤的结果,参数为 documentnamespacequalifiedName 以及一个空字典。

  4. 如果 doctype 非 null,则 doctype 添加到 document

  5. 如果 element 非 null,则 element 添加到 document

  6. document来源document(即 this 所关联文档)的 来源

  7. document内容类型namespace 决定:

    HTML 命名空间
    application/xhtml+xml
    SVG 命名空间
    image/svg+xml
    其他任意命名空间
    application/xml
  8. 返回 document

createHTMLDocument(title) 方法的步骤如下:

  1. doc 为一个新的 文档,其类型为 HTML 文档

  2. doc内容类型设为 "text/html"。

  3. 追加一个新的 doctype,其 名称为 "html",节点文档doc,追加到 doc

  4. 追加调用 创建元素,参数为 doc、"html"、HTML 命名空间,结果追加到 doc

  5. 追加调用 创建元素,参数为 doc、"head"、HTML 命名空间,结果追加到之前创建的 html 元素。

  6. 如果参数 title 被给定:

    1. 追加调用 创建元素,参数为 doc、"title"、HTML 命名空间,结果追加到之前创建的 head 元素。

    2. 追加一个新的 Text 节点,其 数据title(可能是空字符串),节点文档doc,追加到之前创建的 title 元素。

  7. 追加调用 创建元素,参数为 doc、"body"、HTML 命名空间,结果追加到之前创建的 html 元素。

  8. doc来源this 关联的 文档来源

  9. 返回 doc

hasFeature() 方法的步骤是返回 true。

hasFeature() 最初是用于报告用户代理是否支持某个 DOM 功能,但事实证明直接检查所需对象、属性或方法是否存在更为可靠且细致。因此,该接口已不再建议使用,但依然保留(且仅返回 true),以避免老页面无法工作。

4.6. 接口DocumentType

[Exposed=Window]
interface DocumentType : Node {
  readonly attribute DOMString name;
  readonly attribute DOMString publicId;
  readonly attribute DOMString systemId;
};

DocumentType 节点通常称为文档类型

文档类型具有关联的名称公共 ID系统 ID

创建文档类型时,总是会给出其名称。除非在创建文档类型时明确指定,否则其公共 ID系统 ID 均为空字符串。

name getter 的步骤是返回此对象名称

publicId getter 的步骤是返回此对象公共 ID

systemId getter 的步骤是返回此对象系统 ID

4.7. 接口DocumentFragment

[Exposed=Window]
interface DocumentFragment : Node {
  constructor();
};

DocumentFragment 节点有一个关联的 宿主(host) (可以为 null 或位于不同 节点树中的 元素)。除非另有说明,否则为 null。

如果对象 A 是对象 B包含宿主的包容祖先(host-including inclusive ancestor), 则表示要么 AB包容祖先, 要么 B根节点有一个非 null 的 宿主(host), 且 AB根节点宿主(host) 的包含宿主的包容祖先。

DocumentFragment 节点宿主(host) 概念对于 HTML 的 template 元素以及 shadow root 很有用,并且会影响 预插入替换算法。

tree = new DocumentFragment()
返回一个新的 DocumentFragment 节点

new DocumentFragment() 构造步骤为:设置 this节点文档当前全局对象关联 Document

4.8. 接口 ShadowRoot

[Exposed=Window]
interface ShadowRoot : DocumentFragment {
  readonly attribute ShadowRootMode mode;
  readonly attribute boolean delegatesFocus;
  readonly attribute SlotAssignmentMode slotAssignment;
  readonly attribute boolean clonable;
  readonly attribute boolean serializable;
  readonly attribute Element host;

  attribute EventHandler onslotchange;
};

enum ShadowRootMode { "open", "closed" };
enum SlotAssignmentMode { "manual", "named" };

ShadowRoot 节点被简称为 影子根(shadow root)

影子根相关联的 host 永远不会为 null。

影子根有一个关联的 模式(mode)("open" 或 "closed")。

影子根有一个关联的 委托焦点(delegates focus) (布尔值)。初始值为 false。

影子根有一个关联的 对内部元素可用(available to element internals)(布尔值)。初始值为 false。

影子根有一个关联的 声明式(declarative) (布尔值)。初始值为 false。

影子根有一个关联的 插槽分配方式(slot assignment) ("manual" 或 "named")。

影子根有一个关联的 可克隆(clonable)(布尔值)。 初始值为 false。

影子根有一个关联的 可序列化(serializable)(布尔值)。 初始值为 false。

影子根有一个关联的 自定义元素注册表 (null 或 CustomElementRegistry 对象)。初始为 null。

影子根有一个关联的 保持自定义元素注册表为 null(keep custom element registry null)(布尔值)。 初始值为 false。

这只有在与声明式影子根(declarative shadow roots)一起使用时才会为 true。 并且这只在影子根自定义元素注册表 仍为 null 时才有意义。


一个影子根get the parent 算法, 给定 event,如果 eventcomposed 标志没有设置、且影子根event路径第一个结构体的 invocation target,则返回 null; 否则返回 影子根host


mode 的 getter 步骤为返回 this模式(mode)

delegatesFocus 的 getter 步骤为返回 thisdelegates focus

slotAssignment 的 getter 步骤为返回 thisslot assignment

clonable 的 getter 步骤为返回 thisclonable

serializable 的 getter 步骤为返回 thisserializable

host 的 getter 步骤为返回 thishost


onslotchange 属性是 事件处理器 IDL 属性, 用于 onslotchange 事件处理器,其 事件类型slotchange


包含 shadow 的树顺序(shadow-including tree order) 是对 节点树带 shadow 的先序深度优先遍历带 shadow 的先序深度优先遍历(shadow-including preorder, depth-first traversal),对 节点树 tree,是对 tree 的先序深度优先遍历。在遍历 tree 时,每遇到一个 shadow host, 紧接着遍历该 元素shadow root节点树

shadow-including root(包含 shadow 的根) 指一个对象的 hostshadow-including root,如果该对象的 影子根;否则为它自己的

对象 Ashadow-including descendant(包含 shadow 的后代), 对于对象 B,当且仅当 A后代,或 A影子根并且 Ahostshadow-including inclusive descendant(包含 shadow 的自身或后代) B

shadow-including inclusive descendant(包含 shadow 的自身或后代) 指对象自身或它的 shadow-including descendant

对象 Ashadow-including ancestor(包含 shadow 的祖先), 当且仅当 Bshadow-including descendant A

shadow-including inclusive ancestor(包含 shadow 的自身或祖先) 指对象自身或它的 shadow-including ancestor

一个 节点 A 若对 节点 B 满足下列所有条件,即认为 closed-shadow-hidden(被 closed 模式的影子 DOM 隐藏)

要对对象 A 针对对象 B 进行 retarget(重定向),重复下列步骤直到返回一个对象为止:

  1. 如果下列条件之一为真

    则返回 A

  2. A 设为 A根节点宿主

retarget(重定向)算法被 事件分派 以及其他规范(如 Fullscreen)使用。[FULLSCREEN]

4.9. 接口 Element

[Exposed=Window]
interface Element : Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString tagName;

  [CEReactions] attribute DOMString id;
  [CEReactions] attribute DOMString className;
  [SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
  [CEReactions, Unscopable] attribute DOMString slot;

  boolean hasAttributes();
  [SameObject] readonly attribute NamedNodeMap attributes;
  sequence<DOMString> getAttributeNames();
  DOMString? getAttribute(DOMString qualifiedName);
  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] undefined setAttribute(DOMString qualifiedName, (TrustedType or DOMString) value);
  [CEReactions] undefined setAttributeNS(DOMString? namespace, DOMString qualifiedName, (TrustedType or DOMString) value);
  [CEReactions] undefined removeAttribute(DOMString qualifiedName);
  [CEReactions] undefined removeAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] boolean toggleAttribute(DOMString qualifiedName, optional boolean force);
  boolean hasAttribute(DOMString qualifiedName);
  boolean hasAttributeNS(DOMString? namespace, DOMString localName);

  Attr? getAttributeNode(DOMString qualifiedName);
  Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setAttributeNode(Attr attr);
  [CEReactions] Attr? setAttributeNodeNS(Attr attr);
  [CEReactions] Attr removeAttributeNode(Attr attr);

  ShadowRoot attachShadow(ShadowRootInit init);
  readonly attribute ShadowRoot? shadowRoot;

  readonly attribute CustomElementRegistry? customElementRegistry;

  Element? closest(DOMString selectors);
  boolean matches(DOMString selectors);
  boolean webkitMatchesSelector(DOMString selectors); // legacy alias of .matches

  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // legacy
  undefined insertAdjacentText(DOMString where, DOMString data); // legacy
};

dictionary ShadowRootInit {
  required ShadowRootMode mode;
  boolean delegatesFocus = false;
  SlotAssignmentMode slotAssignment = "named";
  boolean clonable = false;
  boolean serializable = false;
  CustomElementRegistry? customElementRegistry;
};

ShadowRootInit 有些不同寻常地允许向其 customElementRegistry 成员传递 undefinednull,从而允许 Web 开发者将 ShadowRoot 节点而不是字典传递给 attachShadow()

Element 节点通常称为元素

元素具有关联的:

命名空间
Null 或非空字符串。
命名空间前缀
Null 或非空字符串。
本地名称
一个非空字符串。
自定义元素注册表
Null 或一个 CustomElementRegistry 对象。
自定义元素状态
"undefined"、"failed"、"uncustomized"、"precustomized" 或 "custom"。
自定义元素定义
Null 或一个自定义元素定义
is
Null 或一个有效的自定义元素名称

元素创建时,所有这些值都会被初始化。

一个元素,其自定义元素状态为 "uncustomized" 或 "custom" 时,被称为已定义。一个元素,其自定义元素状态为 "custom" 时,被称为自定义

元素是否已定义用于确定 :defined 伪类的行为。元素是否自定义用于确定突变算法的行为。"failed" 和 "precustomized" 状态用于确保如果自定义元素构造函数第一次未能正确执行,则不会通过升级再次执行。

以下代码展示了处于这四种状态中的元素:

<!DOCTYPE html>
<script>
  window.customElements.define("sw-rey", class extends HTMLElement {})
  window.customElements.define("sw-finn", class extends HTMLElement {}, { extends: "p" })
  window.customElements.define("sw-kylo", class extends HTMLElement {
    constructor() {
      // super() intentionally omitted for this example
    }
  })
</script>

<!-- "undefined" (not defined, not custom) -->
<sw-han></sw-han>
<p is="sw-luke"></p>
<p is="asdf"></p>

<!-- "failed" (not defined, not custom) -->
<sw-kylo></sw-kylo>

<!-- "uncustomized" (defined, not custom) -->
<p></p>
<asdf></asdf>

<!-- "custom" (defined, custom) -->
<sw-rey></sw-rey>
<p is="sw-finn"></p>

元素 还有一个关联的 影子根(null 或 一个 影子根)。除非另有说明,否则为 null。若其 shadow root 非空,则该 元素 为一个 shadow host

若一个 元素命名空间前缀 为 null,则其 限定名称 为其 本地名称; 否则为其 命名空间前缀,后接 ":",再接其 本地名称

一个 元素HTML 大写化的限定名称 是以下步骤的返回值:

  1. qualifiedName 等于 thisqualified name

  2. 如果 this 属于 HTML 命名空间,且其 节点文档HTML 文档,则将 qualifiedName 转为 ASCII 大写形式。

  3. 返回 qualifiedName

用户代理可以通过将 qualified nameHTML 大写 qualified name 存储于内部槽位来优化处理。

创建元素,给定 document document、字符串 localName、字符串或 null namespace,以及可选的字符串或 null prefix(默认 null)、字符串或 null is(默认 null)、布尔值 synchronousCustomElements(默认 false)、"default"、null 或 CustomElementRegistry 对象 registry(默认 "default"):

  1. result 为 null。

  2. 如果 registry 是 "default",则将 registry 设置为给定 document 查找自定义元素注册表的结果。

  3. definition 为给定 registrynamespacelocalNameis 查找自定义元素定义的结果。

  4. 如果 definition 非 null,并且 definition名称不等于其本地名称(即 definition 表示一个自定义的内置元素):

    1. interfacelocalNameHTML 命名空间元素接口

    2. result 设置为给定 documentinterfacelocalNameHTML 命名空间prefix、"undefined"、isregistry 创建元素内部的结果。

    3. 如果 synchronousCustomElements 为 true,则在捕获任何异常的同时运行此步骤:

      1. 使用 definition 升级 result

      如果此步骤抛出异常 exception

      1. definition构造函数的相应 JavaScript 对象的关联领域全局对象报告 exception

      2. result自定义元素状态设置为 "failed"。

    4. 否则,给定 resultdefinition 将自定义元素升级反应加入队列

  5. 否则,如果 definition 非 null:

    1. 如果 synchronousCustomElements 为 true:

      1. Cdefinition构造函数

      2. 设置周围代理活动自定义元素构造函数映射[C] 为 registry

      3. 在捕获任何异常的同时运行这些步骤:

        1. result 设置为构造 C 的结果,不带参数。

        2. 断言:resultcustom element statecustom element definition 已初始化。

        3. 断言:resultnamespaceHTML 命名空间

          IDL 保证 resultHTMLElement 对象,且都使用 HTML 命名空间

        4. 如果 result属性列表 非空, 则抛出 "NotSupportedError" DOMException

        5. 如果 result