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;
上面代码的对应关系图:
