ECMAScript对象和DOM BOM对象是一个概念么?

一个概念。

DOM 和 BOM 并不属于 JavaScript(ECMAScript ) 语言的一部分。DOM 和 BOM 是 JavaScript 的运行平台(浏览器)提供的,比如在 nodejs 中就没有 DOM 和 BOM。

JavaScript 类型分为 2 大类:原生类型和对象类型。而 DOM 和 BOM 都是对象类型。

比如 html 中的段落 p 映射为 JavaScript 对象是 HTMLParagraphElement,顾名思义 Paragraph 就是英语“段落”的意思。

我们看看 HTMLParagraphElement 的继承关系:

HTMLParagraphElement
 - HTMLElement
  - Element
   - Node
    - EventTarget
     - Object

所有的 DOM 和 BOM 没有任何特殊之处,都是一个 Object 的子类。

var div = document.createElement("div"); // 创建一个 div dom
div.foo = 1234;  // 给 div 添加属性
div.sayHello = function(str) {
  console.log("hello " + str);
}

当我们创建了一个 DOM Object 后,我们就可以把这个 DOM Object 当作一个普通的 JavaScript 对象来使用。

说他特殊,大概是因为 DOM 的属性和方法会被引擎映射到 html 标签上。有些会,有些不会,有些只能从 html 到 dom 映射,有些只能从 dom 到 html 映射。这个得需要一篇单独的文章来讲了。。。


如果但从对象的角度讲,特殊的不是 DOM 和 BOM,而是另一个值:

Object.create(null);

所有的 JavaScript 对象都是继承自 Object,即使我们经常创建的空对象:

let obj = {};

也是 Object 的子类。

但是 Object.create(null) 却是实实在在的空对象:


既然讲到这儿了,就再补充点知识点。

在引擎(V8)内部,DOM 对象映射为 C++ Object:

而每个 html 标签都对应一个 DOM Object。

我们看如下代码:

var div = document.createElement("div"); // 创建一个 div dom
div.foo = 1234;  // 给 div 添加属性
var p = document.createElement("p");  // 创建一个 p dom
p.appendChild(div); // 把 div 添加为 p 的子节点
div = null;  // div 设置为空
console.log(p.firstChild.foo); 

可能我们会觉得最终输出的是 null、或者 undefined、或者抛异常。

其实这行代码会输出 1234。


DOM 如何与 JavaScript Object 关联在一起的规范定义在 WebIDL Level 1,WEBIDL 就是 Web Interface Definition Language 的缩写。

如无特殊说明,后面的文章都是以 V8 引擎为例。

DOM Object 在引擎内部是一个 C++ Object,当 JavaScript 操作这个 DOM 时,引擎使用一个 wrapper object,也就是 JavaScript Object。

Wrapper Object 和 DOM Object 的关系是 n : 1(n >= 0)

  • 当 n == 0 时,此 DOM Object 不能通过 JavaScript 访问
  • 当 n == 1 时,此 DOM Object 只有一个 JavaScript Object 可以访问
  • 当 n > 1 时,此 DOM Object 可以通过多个 JavaScript 访问

举个例子:

div = document.createElement("div");
div.innerHTML = "<p><span>foo</span><br></p>";
div.firstChild;

上面代码的对应关系图:

 

THE END