JavaScript由哪三部分组成:ECMAScript、DOM与BOM详解

作者:窗边听雨

时间:2026-10-30

浏览:505

深入解析JavaScript的核心三大部分:ECMAScript、DOM与BOM的职责定义、技术边界、核心API及协同工作机制,助你建立清晰扎实的前端底层认知。

文章目录

日常在浏览器中运行的 JavaScript 并非单一的技术实体,而是一套完整的运行时技术体系。对于运行在浏览器宿主环境中的 JavaScript 而言,它由三大部分紧密结合而成:核心语言语法规范 ECMAScript、文档对象模型 DOM(Document Object Model) 以及浏览器对象模型 BOM(Browser Object Model)。理解这三者的职责边界与协作机制,是理清前端开发脉络的基础前提。

JavaScript由哪三部分组成:ECMAScript、DOM与BOM详解
图 1:JavaScript 核心技术组成架构关系图

一、ECMAScript:语言的语法基础与逻辑核心

ECMAScript 是由 ECMA 国际(Ecma International)通过 ECMA-262 标准制定的脚本语言规范。JavaScript 正是这套规范最著名的一种实现。简单来说,ECMAScript 规定了这门语言“应该长什么样”,以及“代码如何解析和执行”。

ECMAScript 负责的范畴包含且仅包含语言本身的纯粹逻辑,具体包括:

  • 语法与词法结构:关键字、保留字、操作符、代码注释规范。
  • 类型系统:基本原始类型(Number、String、Boolean、Null、Undefined、Symbol、BigInt)与引用对象类型(Object)。
  • 语句与控制流:条件分支(if-else、switch)、循环结构(for、while、for...of)。
  • 核心内置对象:Array、Date、RegExp、Math、JSON、Map、Set、Promise 等数据结构与工具。
  • 内存机制与原型继承:执行上下文、作用域链、闭包、垃圾回收机制以及基于原型的面向对象继承。

需要明确的是,ECMAScript 本身是一个纯粹的抽象标准,它完全不包含任何与浏览器、网络请求或网页元素相关的 API。你在代码中写下 let sum = [1, 2, 3].reduce((a, b) => a + b, 0); 时,这里的所有语法和计算全部由 ECMAScript 引擎定义与执行;无论是运行在 Chrome 浏览器还是服务端的 Node.js 中,这段代码的执行表现是完全一致的。

// 纯粹的 ECMAScript 逻辑示例:类定义、解构赋值与异步处理
class TaskQueue {
  constructor(name) {
    this.name = name;
    this.tasks = [];
  }

  addTask(fn) {
    this.tasks.push(fn);
  }

  async runAll() {
    const results = [];
    for (const [index, task] of this.tasks.entries()) {
      const res = await task();
      results.push({ index, res });
    }
    return results;
  }
}

二、DOM:将网页结构转化为可编程对象的桥梁

仅有 ECMAScript 只能完成内存中的运算,却无法在屏幕上绘制任何按钮或读取输入框的文字。让代码能够与网页内容互动的桥梁就是 DOM(Document Object Model,文档对象模型)。

DOM 是 W3C 和 WHATWG 组织制定的跨平台标准接口。当浏览器加载 HTML 文档时,解析引擎会把纯文本标签解析为一棵由节点(Node)构成的层次化对象树。在 DOM 视角下,HTML 页面中的每一个标签、文本片段甚至属性,都被抽象为一个可以被 JavaScript 访问和修改的对象。

JavaScript由哪三部分组成:ECMAScript、DOM与BOM详解
图 2:DOM 节点树结构与 JavaScript 经典交互链路

DOM 为开发者提供了四大维度的操作能力:

  1. 节点查找与选择:通过 document.getElementById()、document.querySelector()、document.querySelectorAll() 在文档树中快速检索目标元素。
  2. 内容与属性变更:通过 element.textContent、element.innerHTML 更改文本与HTML;通过 element.setAttribute()、element.classList 动态修改样式类与自定义属性。
  3. 节点增删与层级调整:通过 document.createElement() 创建新节点,并通过 parentElement.appendChild() 或 remove() 动态挂载或卸载页面元素。
  4. 事件监听与分发:通过 element.addEventListener() 捕获用户在界面上的点击、键盘敲击、滚动、触控等操作,并利用冒泡与捕获机制实现事件委托。
// 典型的 DOM 交互操作实例
const submitBtn = document.querySelector('#submit-btn');
const statusText = document.querySelector('.status-message');

submitBtn.addEventListener('click', () => {
  // 动态修改 DOM 内容与样式类
  statusText.textContent = '数据提交中,请稍候...';
  statusText.classList.add('loading');
  submitBtn.disabled = true;
});

三、BOM:与浏览器窗口及客户端环境交互

如果说 DOM 关注的是网页文档内部的骨架与内容,那么 BOM(Browser Object Model,浏览器对象模型) 关注的就是承载这个网页的“外壳”——浏览器窗口与运行环境本身。

BOM 提供了一整套脱离网页内容本身、专门用于操作浏览器宿主能力的 API 集合。由于早期缺乏官方统一标准化,各大浏览器厂商自行实现了各种对象;但目前 WHATWG 已将主流 BOM 接口系统化地收录于 HTML 现行标准(HTML Living Standard)中。

JavaScript由哪三部分组成:ECMAScript、DOM与BOM详解
图 3:BOM 核心对象树结构与 Window 顶层关系图

BOM 的绝对中枢是 window 对象。在浏览器中,window 具有双重身份:它是全局作用域的顶层容器,同时也是浏览器窗口的直接代言人。BOM 的核心子对象包括:

  • location:表示当前加载文档的 URL 信息。支持通过 location.href 实现页面跳转,通过 location.search 获取查询字符串参数,或通过 location.reload() 重新加载当前页面。
  • history:提供对浏览器会话历史栈的受限访问。支持 history.back()、history.forward() 以及在现代单页应用(SPA)中极其关键的 history.pushState() 与 history.replaceState(),实现无刷新变更路由地址。
  • navigator:提供运行该页面的客户端环境信息,例如网络连接状态(navigator.onLine)、系统首选语言(navigator.language)、剪贴板访问接口(navigator.clipboard)等。
  • screen:包含关于用户物理显示设备的信息,如屏幕整体分辨率(screen.width / screen.height)与可用显示区域(screen.availHeight)。
  • 定时器与原生弹窗:setTimeout、setInterval、requestAnimationFrame 以及传统的 alert、confirm 等全局函数均属于 BOM 的能力范畴。
// BOM 核心对象的日常使用示例
// 1. 获取 URL 中的查询参数
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('uid');

// 2. 检测网络连线状态
if (!window.navigator.onLine) {
  console.warn('当前处于离线状态,部分网络功能将暂停');
}

// 3. 监听窗口大小变化(视口自适应)
window.addEventListener('resize', () => {
  const innerW = window.innerWidth;
  console.log(`当前窗口视口宽度: ${innerW}px`);
});

四、三者如何协同工作与维度对比

在实际的 Web 开发场景中,ECMAScript、DOM 与 BOM 永远不是孤立存在的,它们在每一个交互动作中紧密配合。以一个最常见的“用户点击表单按钮并提交保存”流程为例:

  • 用户点击按钮,浏览器的 BOM/DOM 事件机制 捕获到点击行为,分发 click 事件;
  • 事件触发后,由 ECMAScript 编写的回调函数进入执行栈,负责校验输入参数、计算业务哈希、处理数据逻辑;
  • 校验通过后,通过 BOM 提供的 fetch / XMLHttpRequest 向后端服务器发起异步网络请求;
  • 请求成功返回,脚本通过 DOM API 动态在页面中插入一条新的列表节点并清除输入框内容;
  • 最后调用 BOM 的 history.pushState() 更新地址栏 URL,实现页面路由的静默更新。
JavaScript由哪三部分组成:ECMAScript、DOM与BOM详解
图 4:ECMAScript、DOM 与 BOM 核心维度对比与职责矩阵

五、开发者常见疑问与边界辨析

1. Node.js 中也有 DOM 和 BOM 吗?

没有。Node.js 只是一个基于 V8 引擎的服务端运行时环境。它完整实现了 ECMAScript 标准,但它并不具备浏览器窗口,因此没有原生的 BOM(没有 window、location 等对象);同样,由于没有图形化渲染引擎加载 HTML,它也没有原生的 DOM(没有 document)。取而代之的是,Node.js 提供了特有的系统级模块,如 fs(文件系统)、http(网络服务)、path(路径处理)等。如果需要在 Node.js 中解析网页 HTML,必须借助诸如 jsdom 或 cheerio 等第三方库进行模拟。

2. 为什么写 document 可以省略 window?

在浏览器环境中,BOM 的 window 同时扮演了 ECMAScript 的全局对象(Global Object)。在 JavaScript 的作用域链查找规则中,未声明修饰的变量如果在当前作用域链中未找到,最终会落在全局对象上进行匹配。因此,直接访问 document 与访问 window.document 在运行时是完全等价的,同理 location.href 与 window.location.href 亦是如此。

开发建议:在编写现代跨环境代码(例如通用 SDK 或服务端渲染 SSR 应用)时,不可在模块顶层随意假定 window 或 document 始终存在。通常需要通过 typeof window !== 'undefined' 进行宿主环境守卫判断,避免在服务端运行时抛出未定义异常。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章