Node.js 是什么
这篇回答一个基础问题,JavaScript 是怎么从浏览器跑到服务器上的。你会看到浏览器里的 JS 和 Node.js 里的 JS 有什么不同,Node.js 能做什么,以及它和其他后端语言差在哪里。搞清楚这些背景,后面学 fs、http 这些模块才不会一头雾水。
JavaScript 原本只在浏览器里
你之前学的 JavaScript 其实由两部分组成,一个是语言核心,一个是运行环境给的额外能力。
ECMAScript 语言核心
ECMAScript 是 JS 的语言标准,定义了变量声明、运算符、流程控制、函数、对象、数组、类这些基础语法。这部分和运行环境无关,浏览器和服务器里写法完全一样。
const sum = (a, b) => a + b;
console.log(sum(2, 3)); // 浏览器和 Node.js 里输出都是 5
浏览器提供的 Web API
除了语言核心,浏览器还给 JS 塞了一批独有对象,比如操作页面的 document、控制浏览器窗口的 window、获取浏览器信息的 navigator。这些 API 依赖浏览器环境才能存在。
// 这段代码只有在浏览器里才能跑
console.log(window); // 浏览器的全局对象
console.log(document); // 当前页面的文档对象
console.log(navigator); // 浏览器信息,比如版本、语言
在浏览器里,window 是全局对象,console.log 会打开控制台面板。这些都是浏览器给的,语言核心本身并不包含。
Node.js 的诞生
2009 年,Ryan Dahl 把 Chrome 浏览器的 V8 引擎单独拿出来,配上文件系统、网络等一批服务端 API,做出了 Node.js。JavaScript 第一次可以离开浏览器,在服务器上直接运行。
这个思路解决了一个老问题,以前写后端要换一门语言,比如 PHP 或 Java,现在前后端可以都用 JS,一套语法走到底。同时 Node.js 也带火了 npm 这个包生态,2010 年 npm 随 Node.js 一起发布,社区贡献的代码飞速增长,如今已经是全球最大的开源软件仓库。
什么是运行时
运行时(runtime)指程序运行所需的环境总称,包括执行代码的解释器或引擎,以及配套的内置 API。浏览器是一个运行时,它提供 DOM 给 JS 用。Node.js 是另一个运行时,它提供文件系统和网络能力给 JS 用。
两者的关系可以这么记,ECMAScript 是通用语法,浏览器给 JS 配的是网页能力,Node.js 给 JS 配的是服务器能力。
Node.js 的本质
Node.js 的本质可以概括为一句话,ECMAScript 加上 Node.js 自己的 API。
浏览器环境给 JS 配的是 DOM、BOM 这些 Web API,Node.js 给 JS 配的是 fs(文件系统)、http(网络服务)、path(路径处理)、os(操作系统信息)这些服务端 API。两者的语言核心相同,外围能力完全不同。
| 能力 | 浏览器环境 | Node.js 环境 |
|---|---|---|
| window | 有 | 无 |
| document | 有 | 无 |
| DOM / BOM | 有 | 无 |
| global 全局对象 | 无 | 有 |
| process 进程信息 | 无 | 有 |
| fs 文件系统 | 无 | 有 |
| http 服务能力 | 无 | 有 |
在浏览器里写 window 很自然,在 Node.js 里写 window 会直接报 window is not defined,因为 Node.js 环境里根本没有这个对象。后面文章会用 global 和 process 替代它们。
V8 引擎的作用
V8 是 Google 开发的 JavaScript 引擎,负责把 JS 源码编译成机器码再交给 CPU 执行。它的即时编译(JIT)技术让 JS 的执行速度非常快,这也是 Ryan Dahl 当年选中它的原因。
Chrome 浏览器内部用 V8,Node.js 用的也是同一套 V8。所以同样的 JS 代码,在浏览器和 Node.js 里跑,执行性能是同一水平,不需要担心 Node.js 是”缩水版”。
Node.js 的特点
异步非阻塞 I/O
读写文件、发网络请求这类慢操作不会卡住后面的代码。程序先继续往下跑,等结果回来再处理。这点和传统同步模型差别很大,也是新手写 Node.js 时最容易不适应的地方。
console.log("开始");
setTimeout(() => console.log("两秒后执行"), 2000);
console.log("结束");
// 输出顺序是,开始 → 结束 → 两秒后执行
看到没有,setTimeout 没有卡住后面的代码,程序先打印了”结束”,两秒后才回头执行回调。磁盘读写、网络请求都是这个套路,这就是”非阻塞”的含义。
事件驱动
程序的运行围着事件转,文件读完了、请求到达了,都会触发对应的回调函数。写代码时不直接调用,而是注册事件处理函数等它自己触发。
单线程与事件循环
JS 主线程只有一个,靠事件循环排队处理任务,不用像多线程语言那样操心加锁和共享数据。好处是简单,代价是单个计算任务占住线程时,其他任务只能等着。这套模型总结起来一句话,Node.js 擅长等,不擅长算。
Node.js 能做什么
Web 服务器与 API 服务
这是 Node.js 最主流的用途,用内置的 http 模块就能起一个服务器,配合 Express、Koa 等框架可以快速写出 API 接口。它的异步事件模型特别适合聊天、实时推送这类 I/O 密集型的场景。
命令行工具
用 Node.js 可以写命令行程序,读写文件、批量处理数据、自动化脚本都能做。npm 生态里大量 CLI 工具就是 Node.js 写的,比如格式代码的 prettier。
前端构建工具
前端开发常用的 webpack、vite、esbuild 全部运行在 Node.js 上。它们的打包、编译、热更新功能本质上是 Node.js 程序。换句话说,只要做前端开发,电脑里就离不开 Node.js。
和其他后端技术比一比
| 技术 | 特点 | 典型场景 |
|---|---|---|
| Java | 重、类型严格、生态庞大 | 大型企业级系统 |
| Python | 上手快、脚本友好、AI 生态强 | 数据分析、机器学习、自动化脚本 |
| Go | 编译型、部署简单、高并发 | 云原生、微服务、网关 |
| Node.js | 异步 I/O 强、前后端同语言、轻量 | Web API、实时应用、工具链 |
选型没有绝对答案。做 Web API 和开发工具链,Node.js 上手最快,前后端还能共用代码。写底层系统和流量网关,Go 的高并发更稳。企业级业务系统,Java 的生态最成熟。Node.js 不是万能药,CPU 密集型的计算任务它并不擅长,这类场景 Go 和 Java 更合适。但如果你做 Web 开发,希望一套 JS 打通前后端,Node.js 是最顺手的选项。
版本与生态
Node.js 的版本更新很快,官方把版本分成两类,偶数版本号(18.x、20.x)是 LTS 长期支持版,维护周期长、稳定可靠,生产环境都推荐用 LTS。奇数版本是尝鲜版,只维护几个月。本教程所有示例以 Node 20 LTS 为准。
配合 npm registry 上两百多万个开源包,Node.js 的生态基本覆盖了 Web 开发的全部环节,数据库、登录、缓存、消息队列都能找到成熟方案,这也是它流行的重要原因。
实践
这一步先完成安装,安装过程参考 Node.js 环境搭建,按你自己的操作系统选一种方式即可。验证版本用终端操作,Windows 上用 PowerShell 或 CMD,macOS 和 Linux 用自带的终端。装完打开终端输入。
node -v
# 输出类似 v20.18.0,教程基于 Node 20 LTS
npm -v
# 输出类似 10.8.2
能看到版本号说明环境就绪。输入命令后提示找不到 node,一般是安装没成功或者装完没重启终端,回上一篇按排查办法处理。想确认安装位置可以用 where node(Windows)或 which node(macOS 和 Linux),会输出 node 可执行文件的完整路径。环境就绪后就可以开始写代码了。
常见坑
- 以为 Node.js 是一门新语言。它不是,它只是让 JS 跑在服务器上的运行时环境,语法还是 JS。
- 以为 Node.js 是个框架。框架是 Express、Koa 这类,Node.js 是底层运行时,自带
http、fs等基础模块。 - 装了旧版本还在用。版本太老会缺新语法和新 API,教程里的示例以 Node 20 为准,低于 18 的建议先升级。
- 在 Node.js 里写
window或document。这是浏览器专属对象,Node.js 环境会直接报错,对应的是global和process。 - 把 Node.js 当成多线程语言用。它的主线程只有一个,CPU 密集任务会卡住整个进程,这类任务应该交给别的语言或单独进程。
- 在 REPL 里测试代码后直接关掉终端,写的变量和代码全部丢失,正式内容要存在
.js文件里。
装好环境就进入下一关 Node.js 环境搭建,里面还有安装失败的排查办法。