JavaScript 语言概览与历史
JavaScript 是当前 Web 世界使用最广泛的编程语言,诞生于 1995 年,最初只用来在浏览器里做简单的表单校验,如今已经成长为覆盖前端、服务端、桌面端、移动端的全栈语言。理解它的历史、特性与运行机制,是深入学习这门语言的第一课。
JavaScript 是什么
JavaScript 是一门解释型(即时编译)、动态类型、弱类型的多范式编程语言,支持命令式、面向对象和函数式三种编程风格。它由 Netscape 公司的 Brendan Eich 于 1995 年在 10 天内设计完成,最初命名为 Mocha,后改名 LiveScript,最终定名为 JavaScript。
JavaScript 与 Java 除了名字相似之外没有任何血缘关系,两者的对比常被戏称为"Java 与 JavaScript 的关系就像 Car 与 Carpet(地毯)的关系"。
五大核心特征
| 特征 | 说明 |
|---|---|
| 动态类型 | 变量没有固定类型,类型由运行时的值决定,同一个变量可以先后存放字符串、数字、对象 |
| 弱类型 | 不同类型之间可以隐式转换,例如字符串与数字相加会得到字符串拼接结果 |
| 基于原型 | 对象通过原型链(prototype chain)实现继承,而不是像 Java 那样的类继承 |
| 一等函数 | 函数与其他值地位相同,可以赋值给变量、作为参数传递、作为返回值返回 |
| 事件驱动 | 以事件循环(event loop)为核心,配合回调、Promise、async/await 处理异步任务 |
动态类型与弱类型往往被一起讨论,但两者含义不同:动态类型描述"类型在运行时确定",弱类型描述"类型之间可以自动转换"。Python 是动态强类型,Java 是静态强类型,而 JavaScript 是动态弱类型。
// 动态类型:同一变量可以存放不同类型
let value = 42; // 数字
value = "hello"; // 字符串
value = { name: "js" }; // 对象
value = [1, 2, 3]; // 数组
// 弱类型:类型自动转换
console.log(1 + "2"); // 输出 "12",数字被转成字符串做拼接
console.log("5" - 2); // 输出 3,字符串被转成数字做减法
console.log(1 == true); // 输出 true,隐式转换后相等经典语言特性示例
基于原型、一等函数和事件驱动这三个特性,可以用一段代码直观感受:
// 一等函数:函数可以像值一样传递
const double = (n) => n * 2;
[1, 2, 3].map(double); // 输出 [2, 4, 6]
// 基于原型:通过原型链复用方法
const animal = { speak() { return this.name + " 叫了一声"; } };
const dog = Object.create(animal);
dog.name = "旺财";
dog.speak(); // 输出 "旺财 叫了一声"
// 事件驱动:异步回调
setTimeout(() => {
console.log("2 秒后执行");
}, 2000);
console.log("先执行这一行");核心语言特性
JavaScript 在长期演进中积累了一批独有或罕见的设计,理解它们有助于写出更地道的代码。
| 特性 | 描述 |
|---|---|
| 闭包 | 函数可以记住并访问定义时的作用域,即使外层函数已执行完毕 |
| 原型链继承 | 通过 __proto__ 链查找属性与方法,class 语法只是原型继承的语法糖 |
| 一等函数与高阶函数 | 函数可作为参数、返回值,支持 map/filter/reduce 等组合式编程 |
| 异步编程模型 | 单线程 + 事件循环 + 宏任务/微任务,非阻塞处理 I/O |
| 自动垃圾回收 | 基于引用计数与标记清除,开发者无需手动管理内存 |
| 动态对象 | 对象可以随时添加、删除属性,无需声明结构 |
| 松散模式与严格模式 | 严格模式("use strict")收紧部分历史遗留的不安全行为 |
闭包是 JavaScript 中最容易被忽视又最重要的特性,下面的计数器例子展示了闭包捕获局部变量的能力:
function createCounter() {
let count = 0; // 局部变量被闭包捕获
return function () {
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3类型系统与 typeof
JavaScript 共有 8 种数据类型:7 种原始类型(undefined、null、boolean、number、bigint、string、symbol)加 1 种对象类型(object)。typeof 运算符返回值的类型字符串:
typeof undefined; // "undefined"
typeof null; // "object" —— 著名的历史 bug
typeof true; // "boolean"
typeof 42; // "number"
typeof 10n; // "bigint"
typeof "hello"; // "string"
typeof Symbol("s"); // "symbol"
typeof {}; // "object"
typeof []; // "object"
typeof function () {}; // "function" —— 函数虽然是对象,但 typeof 特殊处理typeof null 返回 "object" 是一个历史遗留 bug:早期实现把对象类型标记为 0,而 null 的空指针标记恰好也是 0,于是 typeof null 误判为 "object"。由于修复会影响存量代码,这个 bug 被一直保留至今,判断 null 时应使用 value === null。
主流 JavaScript 引擎对比
JavaScript 引擎是将源代码编译成机器码并执行的程序。浏览器、Node.js 等宿主环境都内置引擎,引擎负责解析、编译、优化与垃圾回收。
| 引擎 | 开发方 | 主要运行环境 | 特点 |
|---|---|---|---|
| V8 | Chrome、Edge、Node.js、Deno、Electron | 市场份额最大,性能最强,采用 Ignition 解释器 + TurboFan JIT 编译器 | |
| SpiderMonkey | Mozilla | Firefox | 最早诞生的 JS 引擎,采用解释器 + IonMonkey JIT |
| JavaScriptCore | Apple | Safari、iOS/ macOS 内置浏览器 | 又称 Nitro,苹果生态性能优化充分,功耗控制出色 |
| Chakra | Microsoft | 旧版 Edge(EdgeHTML) | 曾用于 IE11 与旧 Edge,随新版 Edge 改用 V8 而退出历史舞台 |
除浏览器外,引擎还被封装成可嵌入的运行时:
| 运行环境 | 底层引擎 | 定位 |
|---|---|---|
| Node.js | V8 | 服务端 JavaScript 运行时,自带文件系统、网络等模块 |
| Deno | V8 | Node.js 的继任者,原生支持 TypeScript 与安全沙箱 |
| Bun | JavaScriptCore | 主打性能的新兴运行时,内置包管理器与打包器 |
| QuickJS | 自有引擎 | 可嵌入的轻量引擎,常用于嵌入式场景 |
V8 还派生了多个专用运行时,例如微信小程序使用的 JSCore、支付宝小程序使用的 V8。同一段代码在不同引擎上的表现细节(如字符串编码、数字处理)可能略有差异,但都遵循统一的 ECMAScript 规范,保证语法级兼容。
ECMAScript 发展时间线
JavaScript 的语言规范由 ECMA 国际组织维护,规范名称为 ECMAScript。浏览器厂商以规范为基准实现语言功能,因此"ES 版本"基本等同于"JavaScript 版本"。
| 年份 | 版本 | 里程碑内容 |
|---|---|---|
| 1995 | — | JavaScript 诞生于 Netscape Navigator,10 天设计完成 |
| 1997 | ES1 | 提交到 ECMA 国际组织,成为 ECMA-262 第一版规范 |
| 1998 | ES2 | 小幅修订,为符合 ISO 标准做的编辑性调整 |
| 1999 | ES3 | 奠定现代基础:正则表达式、try/catch、switch 等 |
| 2009 | ES5 | 严格模式、JSON 对象、Object.defineProperty、数组新增方法 |
| 2015 | ES6(ES2015) | 划时代版本:let/const、箭头函数、类、模板字符串、解构、模块、Promise、Symbol |
| 2016 | ES2016 | 指数运算符 **、Array.prototype.includes |
| 2017 | ES2017 | async/await、Object.values、Object.entries、字符串填充 |
| 2018 | ES2018 | 对象/数组展开运算符、Promise.finally、异步迭代器 |
| 2019 | ES2019 | Array.prototype.flat、Object.fromEntries、可选 catch 绑定 |
| 2020 | ES2020 | 可选链 ?.、空值合并 ??、BigInt、Promise.allSettled、动态 import |
| 2021 | ES2021 | String.replaceAll、逻辑赋值运算符、Promise.any |
| 2022 | ES2022 | 类私有字段 #field、顶层 await、Array.prototype.at、Object.hasOwn |
| 2023 | ES2023 | Array.prototype.findLast、toSorted 等数组复制方法、Hashbang 注释 |
| 2024 | ES2024 | Promise.withResolvers、Object.groupBy、正则 v 标志、ArrayBuffer 新方法 |
2000 年到 2009 年之间 ECMAScript 4 一度酝酿大规模改版,最终因各方分歧过大而搁浅,这也是 ES5 与 ES6 之间间隔多年的原因。自 2015 年起,TC39 委员会改为每年发布一个新版本,版本号按年份命名(ES2015、ES2016……),功能则通过"提案成熟度阶段"(Stage 0 到 Stage 4)逐步引入,Stage 4 表示已定稿、进入正式规范。
ES6 是公认的分水岭,此前代码大量依赖 var 与回调嵌套,此后 let/const、箭头函数、模块与 Promise 成为主流写法。ES2020 之后的新特性大多为"锦上添花"的语法糖与便利 API,现代环境(Chrome 90+、Node 16+)已原生支持绝大多数新语法,日常开发通常无需再关注版本差异。
应用场景
JavaScript 凭借"一次学习,处处运行"的生态覆盖了几乎所有开发领域。
| 场景 | 典型技术 | 说明 |
|---|---|---|
| Web 前端 | React、Vue、Angular | 浏览器端唯一的原生编程语言,负责交互、渲染与状态管理 |
| 服务端 | Node.js、Deno、Bun | 高并发 I/O 场景优势明显,支撑大量企业级后端与中间层 |
| 桌面应用 | Electron、Tauri | Electron 用 Web 技术开发跨平台桌面软件,VSCode、Slack 均是实例 |
| 移动端 | React Native、uni-app | 一套 JS 代码编译为 iOS/Android 原生应用 |
| 小程序 | 微信、支付宝小程序 | 小程序生态基于 JavaScript 与类 WXML 模板语法 |
| 游戏开发 | Phaser、Three.js、Cocos | 网页游戏与 3D 可视化,Three.js 用于 WebGL 三维渲染 |
| 嵌入式 | Espruino、JerryScript | 在物联网设备上运行轻量 JavaScript 运行时 |
| 数据可视化 | D3.js、ECharts | 大量图表库基于 Canvas/SVG 实现 |
优缺点分析
优势
- 全栈统一:前后端共用一门语言,团队心智负担小,代码可以跨端复用。
- 生态庞大:npm 是全球最大的软件包仓库,拥有超过 200 万个包,几乎任何需求都能找到现成方案。
- 上手门槛低:语法接近自然语言,在浏览器控制台输入一行即可运行,反馈即时。
- 事件驱动高效:单线程 + 非阻塞 I/O 在并发连接、聊天、流式处理等场景吞吐量高。
- 社区活跃:TC39 规范演进快,框架与工具迭代迅速,就业市场与学习资源丰富。
劣势
- 弱类型隐患:隐式转换与动态类型在大型项目中容易引入难以排查的类型错误,需要 TypeScript 等工具弥补。
- 历史包袱:
var函数作用域、typeof null返回"object"、隐式全局变量等遗留设计长期存在。 - 单线程局限:CPU 密集型任务会阻塞事件循环,需要 Worker 线程或拆分任务来规避。
- 异步复杂度:回调地狱虽被 Promise/async-await 缓解,但错误处理与并发控制仍需谨慎。
- 全局污染风险:早期脚本无模块化机制,容易产生命名冲突,如今依赖 ES Module 与打包工具解决。
小结
JavaScript 从 1995 年一个 10 天设计出来的浏览器脚本语言,历经 ES5 规范定型、ES6 划时代革新、每年一版的持续演进,成长为横跨前后端的通用语言。它动态、弱类型、基于原型、函数一等、事件驱动的特性决定了代码的书写方式与运行模型,V8 等高性能引擎则让它的执行速度足以支撑大型应用。理解这些基本面,后续学习变量、函数、异步等主题时就能知其然也知其所以然。