JavaScript 无处不在 — 这门语言的地基与外挂¶
这一章讲三件事: 这门语言与 Java、C# 的三点根本不同(这是全书后面所有章节的伏笔); 「想用新语法又怕老环境不支持」时的两条出路;以及选框架、做性能、管依赖这三件工程师天天撞上、 教材却很少正面讲的事。读完你会拿到全书的坐标系。
1. 先看现象:一个 10 天项目,跑进了你的汽车¶
1995 年,Netscape 公司想给自己的浏览器加一个脚本语言,前后花了大约 10 天, JavaScript 就出生了。三十年后,你打开的网站、你手机里的应用、你桌上的电子表格、 甚至你汽车的车机——里面都有它的代码。作者引用了一条行业定律来概括这个现象:
任何可以用 JavaScript 写的应用,最终都会用 JavaScript 来写。1
这条「Atwood 定律」是半开玩笑,但它背后有个真问题:一门为「给网页加个小验证」而生的语言, 怎么就成了通用平台的默认选择?原书的答案是两个字:演化。具体来说有三股力:
- 浏览器之间的竞争。 各家浏览器厂商为了让自家网页跑得更快,拼命优化 JavaScript 引擎, 结果是语言本身没变快多少,执行它的机器快了几个数量级。
- 厂商之间的合作。 竞争之外,各家用同一个标准化组织(ECMAScript 委员会)来定新特性, 语言从「多年才更新一次」变成「每年都有新版本」。
- Node.js 的诞生。 有人把浏览器的 JavaScript 引擎拆出来,配上文件系统、网络这些服务器能力, 这门语言就此冲出了浏览器,长出了包管理系统和用 JavaScript 写的 JavaScript 工具。2
这三股力是理解全书的钥匙: 引擎竞争 → 性能提示散见全书;年度标准 → 每个新语法都带「哪年引入」的标签; Node.js → 第 3 章的主角。
这一章的主线例子:一次「新语法」的旅程¶
为了把后面几节串起来,我们跟着书里反复出现的一个困境走一遍:
你:想用最新标准里刚发布的新语法(比如 ES2018 的正则后行断言)
│
├─ 你的浏览器:支持 ✓
├─ 用户的旧浏览器:不支持 ✗
├─ 服务器上的 Node.js:看版本,可能支持一半
└─ 你同事的环境:天知道
问题:同一份代码,怎么在所有地方都能跑?
这个困境在第 2 节(语言差异)、第 3 节(transpiler/polyfill)、第 4 节(框架)里一步步展开解法, 最后第 5 节交代「就算都解决了,还有三个更大的麻烦」。下面逐段走。
2. 与主流语言的三点不同:全书的地基¶
原书开篇就立了一块警示牌:「如果你懂 C# 或 Java,你就已经挺懂 JavaScript 了」——这是个陷阱。3 相似只是语法皮相;掀开皮,有三处结构性的不同,后面九章全在它们的延长线上。
2.1 函数是一等对象¶
一等对象(first-class object) 的意思是:这个东西和数字、字符串、任何别的对象享有同等待遇—— 能存进变量、能塞进数组、能当参数传给别的函数、能由别的函数造出来并返回。4
在 Java 里,函数必须挂在一个类下面才能存在;在 JavaScript 里,函数本身就是一种值:
// 函数存进变量
const greet = function (name) { return "你好 " + name; };
// 函数塞进数组
const pipeline = [greet, (s) => s + "!"];
// 函数当参数传给别的函数(这就是「回调」)
pipeline.forEach((fn) => console.log(fn("忍者")));
这个性质看着简单,却是全书最重的承重墙:第 5 章的定义与参数、第 6 章的 this、
第 7 章的闭包、第 8 章的 promise——每一章都是「函数是个值」的一个推论。
2.2 基于原型的对象,而不是基于类¶
Java/C# 的套路是:先写一张「图纸」(class),再照着图纸批量生产「实例」。 JavaScript 早年没有 class 关键字,它的继承靠的是原型(prototype): 每个对象背后链着另一个对象,读属性时自己身上找不到,就去链上的下一个对象找。5
ES2015 加入了 class 关键字,但原书提醒:那只是语法糖,掀开盖子,底下仍是原型。
(具体怎么个糖法,第 9 章整章在讲,这一章只要记住「有 class ≠ 类的机制」。)
2.3 单线程:代码一次只跑一段¶
JavaScript 的程序从头到尾只有一条线程在执行代码。想一边等网络一边干别的? 语言本身没有这个选项,只能靠「把之后的活儿登记下来,回头再叫我」——这就是回调(callback), 以及后来更现代的 promise 一脉。第 3 章会见到它的第一种形态,第 8 章是它的完整理论。6
三点合起来就是原书对这门语言的速写:函数与闭包、对象与原型,是这门语言内部最要紧的两对关系; 而单线程 + 回调,是它和宿主环境(浏览器、服务器)相处的方式。7
3. 语言的演进节奏:每年一个新版本,以及两条「提前用未来」的路¶
3.1 ECMAScript 是谁,和你有什么关系¶
JavaScript 这个名字有商标麻烦(Sun 公司握有「Java」),所以标准化组织取了个中性的名字: ECMAScript。实践里可以把两者当同义词:官方规范里叫 ECMAScript,日常交流叫 JavaScript。8
节奏上,2015 年的 ES6(后改名 ES2015)是个分水岭:一次性带来了箭头函数、Map、promise、模块等一大批特性; 此后形成惯例——每年一个版本,ES2016、ES2017……书里每个新语法都挂着年份标签,原因就在这。
代价也来了:你写的代码要在「用户的、可能很旧的浏览器」里跑。 查某个特性哪个环境支持,原书指了一个公开的对照表网站(compat-table)。9 但更常见的解法是把「新旧差异」交给工具,见下。
3.2 主线例子的第一步:transpiler,把新语法翻译成旧语法¶
transpiler(转换器,transformation + compiler 的合写)是这样一类工具: 吃进用最新语法写的代码,吐出一份功能等价、但只用旧语法的老代码。10 比如你用 ES2015 的箭头函数写,它能转成等价的普通函数写法,于是一份代码就能在只认识旧语法的环境里跑。 这个做法由 Babel 发扬光大;用 TypeScript 的话,它的编译器顺手就把这件事做了。
3.3 主线例子的第二步:polyfill,老环境里「补装」新功能¶
polyfill(填充物)是另一条路:它不是改你的代码,而是在没有某个新功能的老环境里, 现场用旧功能把那个新功能「实现」一遍。11
书里的例子:promise 是 ES6(2015)加的,但你要支持停在 ES5 的老浏览器,
那就加载一段 polyfill 代码——它定义一个全局的 Promise,行为照抄新标准。
Babel 可以配置成编译时自动把需要的 polyfill 注射进代码。
transpiler 管「语法」,polyfill 管「功能」,两者常一起用。 但原书给了一个重要的边界:
有些特性就是没法在老环境里高效补出来。比如正则的后行断言(ES2018 加入)—— 在没有这个功能的引擎里,相关正则会直接报错,transpile 也救不了。12
所以底线是:始终知道你的代码要跑在哪些环境里。这句话听着像常识, 却是「代码在我机器上好好的」类事故的总根源。
4. 框架地图:项目的第一选择题¶
原书对框架的定义很实际:框架是为你的应用核心功能提供动力的库—— 写网页应用靠它渲染 HTML,写服务器靠它解析 HTTP 请求。不用框架也能做这些事, 但一个合身的框架能省下巨量时间;实际上,现代 JavaScript 项目几乎没有不用框架的。13
书里按运行位置分了三类,我们照抄它的分法:
| 类别 | 干什么 | 书中点名的代表 |
|---|---|---|
| Web 界面框架 | 在浏览器里渲染页面、管交互 | React(及其 JSX 语法)、Angular、Vue、Svelte |
| 服务器框架 | 解析 HTTP 请求、路由到处理函数 | Express(极简)、Adonis(全家桶)、Next.js/Remix/Astro(全栈,含服务端渲染) |
| 应用框架 | 用一套代码产出桌面/手机应用 | Electron、Ionic(内嵌网页视图)、React Native(产出真正的原生控件) |
关于 React 多说一句,因为第 4 章还要展开:它引入的 JSX 语法让你把 HTML 写进 JavaScript 里; 底层用的是虚拟 DOM——先在内存里搭一棵「页面应该长什么样」的树,和真树比对,只把差异部分更新到页面。14
选框架时原书给了一条非常「忍者」的判据:看生态,不看优雅。 新框架可能更精巧, 但选 React 意味着几万个现成的组件库可以直接拿来用。这个「生态即护城河」的观察, 比任何功能对比表都更接近真实世界的决策。15
另一条提醒和主线例子呼应:界面框架带来了一个副作用——很多网站发给浏览器的不再是完整 HTML, 而是一个空页面加大段 JavaScript,用户要等到代码下载并执行完才能看到内容,于是变慢了。 解法叫 SSR(服务端渲染):同一套代码先在服务器上跑一遍,产出完整 HTML 再发给浏览器。16
5. 三个真实的前线问题¶
语言差异补完了、框架选完了,原书用最后一节交代:真正的麻烦在这些地方。
5.1 性能:越方便越臃肿¶
引擎一直在变快,网站却一直在变慢。原书把根因指向代码膨胀(code bloat), 并给了一套「层层偷懒」的激励机制,每一步都合理,合起来就是灾难:
在浏览器端写代码,比在服务器端写容易 → 倾向往浏览器端堆功能
加一个现成包,比从零写功能容易 → 倾向疯狂加依赖
包作者把一个包做大,比拆成多个包容易 → 每个包都拖着大量你用不到的代码
─────────────────────────────────────────────
合起来:大量「永远不执行也要下载和解析」的代码进了用户的浏览器
原书给的对应思路(细节在没出版的后续章):tree shaking(打包时摇掉没用的代码)、 生产环境标记(别把调试代码发上去)、懒加载(用到再下载)。17
5.2 大规模协作:一个代码库装不下所有人¶
一个电商网站可能是三个团队的产品:导航栏一个团队、商品列表一个团队、购物车一个团队。 最简单的架构是一个代码库整体发布——但依赖冲突会逼死人: A 团队想升级 React,整个代码库都得跟着升,别的团队被迫放下自己的功能开发。18
业界的大方向是把代码库切成各团队能独立更新的单元;代价是新问题(同一页面上不同团队的代码怎么独立部署)。 原书预告的解法叫 module federation(模块联邦),细节在后续章——MEAP 里还没有。
5.3 依赖管理:方便的另一面是供应链¶
原书列了四类依赖事故,每一条都是行业真实伤口:
- 升个小版本想拿 bug 修复,却撞上破坏性变更(包作者没遵守版本号约定);
- 直接依赖和间接依赖各装了一个版本,同一份代码两份拷贝在内存里打架;
- 想用 ES 模块格式的包,环境却只认 CommonJS(或反过来)——模块格式的分裂之痛;
- 最坏情况:供应链攻击——你装的第三方包里被人塞了恶意代码,在你开发机或部署环境里直接执行。19
值得记住原书对这一节的态度:JavaScript 的好处是加依赖之前你能读到它的源码; 能读懂源码的人,才谈得上预估一个依赖的风险——这正是「忍者」与普通开发者的分野。
6. 作者的判断与证据¶
这一章是综述章,证据以「行业观察 + 数据引用」为主,代码证据少。分开标:
有书内证据的判断:
- 「开发者写 TypeScript 的时间已超过直接写 JavaScript」——引用 2023 State of JavaScript 调查; 作者甚至说差点把书名改成《TypeScript 忍者秘籍》。20
- 「代码膨胀是网站变慢的最明显原因」——给出的机制是「即使不执行,代码也要被下载和解析」。21
属于作者立场(行业共识级,书内无论证)的判断:
- 「函数式取向是 JavaScript 与普通开发者代码水平差异的关键」——这是全书的纲领性立场,本章第 18 段第一次亮出。
- 「选框架先看生态规模」——经验之谈,无对照数据。
7. 边界与局限¶
- 本章承诺的多章内容不在 MEAP 里。 tree shaking、module federation、ESM vs CommonJS、 workers、codemods——本章全部以「第 14/17/18 章讲」预告,这些章节在这份 PDF 中不存在。 读本拆解时,涉及这些话题的许诺我们以「超出 MEAP 范围」处理,不虚构内容。
- 框架名单过时风险高。 本章写于 2026 年前后,框架格局两年一变; 书中的分类法(界面/服务器/应用)比名单耐用。
- 「10 天造出」是广为流传的说法,原书照引;语言细节史不在本书范围,此处不作考据。
8. 可带走的(合上这一章,你应该有这八条)¶
- 三个根本差异背下来:函数是一等对象、对象基于原型、代码单线程跑。后面九章全是它们的展开。
- ECMAScript ≈ JavaScript 的同义词,官方文件用前者;特性按年命名(ES2015、ES2018……)。
- 想提前用新特性:transpiler 把新语法翻译成旧语法(Babel、TypeScript 编译器), polyfill 在老环境里补装新功能;两者都救不了的特性(如正则后行断言)要避开。
- 查兼容性用公开对照表,但更要养成「知道我代码跑在哪」的习惯。
- 框架是动力层的库,按运行位置分三类;选型的第一变量是生态规模,不是功能表。
- SSR 的存在动机:纯 JavaScript 渲染的页面,用户要干等代码下载执行才能看到内容。
- 性能问题的结构性根因是代码膨胀,而膨胀来自三层「哪边容易走哪边」的激励。
- 依赖即供应链风险;装包前读源码,是这门语言给你的、别的语言少有的一份防御能力。
9. 深读一:运行时与引擎,分层看清「你的代码在哪跑」¶
第 1 节把「引擎竞争」说成一股抽象的力,这一节把它落到具体的分层图上—— 因为「这段代码在哪一层执行」是排查任何 JavaScript 问题的第一问。
9.1 四层分工:语言、引擎、运行时、宿主¶
┌─────────────────────────────────────────────┐
│ 宿主环境:操作系统(Windows、macOS、iOS……) │
│ ├─ 浏览器(Chrome、Safari、Edge、Firefox) │
│ ├─ 独立运行时(Node.js、Deno、Bun) │
│ └─ 应用外壳(Electron、React Native 的原生层)│
│ ↑ 它们各自提供一批 API 绑定 │
│ 运行时(runtime):能执行 JS 代码的环境 │
│ └─ 内置一个引擎 + 一套 API │
│ ↑ 引擎把 JS 代码变成 CPU 指令 │
│ 引擎(engine):V8(Chrome、Node)、 │
│ JavaScriptCore(Safari、Bun)…… │
│ ↑ 执行的是 ECMAScript 标准定义的语言 │
│ 语言:ECMAScript(每年一个版本) │
└─────────────────────────────────────────────┘
关键的一句:引擎只负责 ECMAScript 标准定义的那部分语言;你的代码能「读文件」、
「发网络请求」、「操作页面」,全靠所在运行时提供的 API 绑定。
浏览器给你 DOM 和 fetch,Node 给你 fs 和 TCP——同一段 console.log,
两边的实现不同,但语言行为一致。9
这对日常开发的直接含义:
- 换运行时 ≈ 换一套 API,不换语言。 第 3 章的 Node 代码搬到浏览器,语法逐字成立,
但
node:fs换成什么、还能不能用,是运行时问题; - 引擎差异通常不用你管。 引擎在持续优化、支持新 ECMAScript 特性; 但「为了写高效的代码,对引擎怎么把代码翻译成机器码有点概念是有帮助的」—— 所以全书散落着性能提示(第 7 章的惰性解析、第 10 章的头部操作代价,都是这一层的事)。
9.2 代码可以「越界」:jsdom 与 WebContainers 两个方向¶
原书记了一对有趣的互相模拟:10
- 在 Node 里模拟浏览器:jsdom 库用纯 JavaScript 实现了一套 DOM—— 用途是测试(不真开浏览器跑页面逻辑)和预渲染(先产出 HTML 再发给用户);
- 在浏览器里模拟 Node:WebContainers 技术让 Node 跑在浏览器沙箱里—— 用途是安全的代码执行环境,以及「不用装任何东西」的开发环境 (第 13 章会见到它的产品形态 StackBlitz)。
Lodash 是另一个方向的例子:它是「为跨运行时而生」的库,浏览器、服务器、应用里都能用, 因为它的代码只依赖语言本身 + 极少数通用 API。给你的判断题:当你写一个库时, 想让它在哪跑,就依赖哪几层——只依赖语言层最自由,依赖越多运行时 API,可移植性越窄。
10. 深读二:框架三类,逐个看清「它替你管什么」¶
第 4 节给了三类框架的名字清单,这里把书里的代表各走一遍—— 选型不看广告,看「它把哪层复杂性吞掉了」。
10.1 界面框架:React 的计数器,逐行看 JSX 管什么¶
书里给了一个 React 计数器的完整组件,我们逐行走一遍它替你做的每件事:11
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // ① 状态:一个数,和改它的合法通道
return ( // ② 返回值描述「页面该长什么样」
<div>
<div>The count is {count}.</div> // ③ 花括号:把 JS 值嵌进 HTML 描述
<button
onClick={() => { // ④ 事件处理器直接写在标签上
setCount(count + 1); // ⑤ 改状态 → React 负责更新页面
}}
>
Increment count
</button>
</div>
);
}
五步各消掉一类手工活:① 状态有了管理规则(不许直接改,必须走 setCount); ②③ 页面是「返回值」而不是一串 DOM 命令;④ 注册事件不再需要 addEventListener; ⑤ 改完状态不用你碰 DOM——React 比对后自己更新。 对照第 04 章的「按键记事本」纯 DOM 版,同一个应用,手工步骤从十几行缩到几行, 代价是引入框架本身的代码量和虚拟 DOM 的抽象(第 04 章末尾的三宗代价)。
挑战者的分化(书里一句话带过,值得展开):Angular、Vue、Svelte 多数采用 JSX 或类似的模板语法,也就是在 React 的范式上做自己的变体,而不是推翻它—— 这是「范式已收敛、实现可竞争」的信号。选型真正要权衡的变量, 书里给的是生态:React 背后有几千个现成组件库,新框架再优雅, 你要的日期选择器、图表、富文本编辑器可能都要自己造。12
10.2 服务器框架:Express 的五行,和「极简 vs 全家桶」光谱¶
Express 的例子短到可以整段记住:13
import express from "express";
const app = express(); // ① 造一个服务器实例
app.get("/ping", (req, res) => { // ② 给路径注册处理器
res.send("OK"); // ③ 发响应
});
服务器框架的本质工作就一件:把 HTTP 请求路由到处理函数。 Express 把这件事做到了极简——不提供的不给;需求一多(身份验证、国际化、 数据库查询),你就要么自己拼装,要么换「带电池」的:Adonis 自带认证、i18n、 ORM(对象关系映射,用代码对象的方式查 SQL 数据库);CMS 型如 Keystone, 为博客、网店这类内容站提供「少配置就能跑」的底座。14
光谱另一头是全栈框架:Next.js、Remix、Astro 把「服务器 + 界面」揉成一体, 默认做服务端渲染(第 1 节那条「空页面等 JS」的解药),并把站点的代码切成块, 只把当前页面用得着的部分发给浏览器;开发体验上带本地 dev server 和 HMR (热模块替换:改一行代码,浏览器不刷新就更新)。记住这条光谱, 你的问题「该用哪个框架」就有了坐标:极简(Express)→ 全电池(Adonis)→ 内容站(Keystone)→ 全栈一体化(Next.js/Remix/Astro)。
10.3 应用框架:「写一次,处处跑」的两种兑现方式¶
桌面和手机是 JavaScript 的第三战场,书里的卖点是写一次,处处跑: 不用为 iOS 写 Swift、为 Android 写 Kotlin、为 Windows 写 C#, 一套 JavaScript 覆盖全部平台——外加 Web。15
两种兑现方式的分水岭在「UI 是谁画的」:
- 内嵌网页视图:Electron(桌面)、Ionic(手机)在原生应用里嵌一个浏览器视图, UI 就是普通 HTML/CSS。名声一度很差(慢、不像原生),但书里点了名: Slack、Notion、Figma 都是这条路——用对组件库、抠好细节,体验可以很好;
- 原生控件:React Native 不画 HTML,而是用 JSX 描述平台原生组件——
<View>在 iOS 上变成 UIView、在 Android 上变成 android.view。 结果是「看起来像每个平台单独写的」:Discord、Pinterest、Skype 是它的名片。
判据依旧朴素:你的团队是 Web 技术栈,就选「让 Web 技能直接变现」的路线; 要对每个平台的观感较真,React Native 的方案上限更高。
11. 深读三:最佳实践三件,各自的「防线画在哪」¶
第 1 章点名了 type checking、linting/formatting、testing 三件, 第 02 章会实操前两件,这里先把三者的防线位置讲清——它们是三道不同的网,网眼不同。
11.1 三道网各拦什么¶
| 网 | 拦什么 | 拦不住什么 | 主力工具(书里点名) |
|---|---|---|---|
| 类型检查 | 类型的误用(把字符串当数字传) | 逻辑错(算法本身写错) | TypeScript |
| Lint/格式化 | 坏模式、风格漂移 | 行为对不对 | ESLint、Prettier |
| 测试 | 行为偏离预期 | 你没写的场景 | Vitest/Jest/Mocha(单元)、Playwright/Cypress(端到端) |
测试那行值得展开,因为书里的二分法(单元 vs 端到端)是协作时的共同语言:16
- 单元测试:把代码隔离测——网络请求等外部依赖被 mock(用写死的假数据顶替, 那些假数据叫 fixture)。快、不怕断网,但测不到「系统各部分真正对接时」才暴露的问题;
- 端到端测试:把代码放进真系统测——用户输入是模拟的,但数据库、第三方 API 都是真的, 在真浏览器里打部署好的站点。慢、脆(网络一抖就误报),但补的是单元测试的盲区: 「两个模块各自都对、连在一起就错」的那类故障。
而书里正文示例的验证手段是第三件小工具:console.assert(条件, 消息)——
条件成立无输出,不成立打印消息。它不是测试框架(没有套件、没有报告),
只是「 sanity check(健全性检查)」的轻量姿势;理解它只需看一个两行的例子。17
12. 深读四:三条前线的完整论证¶
12.1 性能:代码膨胀的会计账¶
把第 5 节的激励机制展开成一笔账。设一个中型站点依赖 200 个包,每个包平均只被用到 三成功能(书里三行激励各自贡献一分),结果:全部代码的约七成从不执行, 但仍要被下载、被解析。用户付的账有三笔——带宽(下载)、CPU(解析编译)、 白屏时间(两者相加)。SEO 再把账算回公司头上:搜索引擎给慢页降排名, 点进来的用户等几秒就走。原书因此把「把慢站变快」称为一项 「有价值(且可度量)的服务」——忍者的绩效点。18
对策三类(细节在没出的后续章,这里只立坐标):tree shaking 让打包器把没被 import 的代码摇掉;生产环境标志让调试代码不进发布产物;懒加载让首屏用不到的代码推迟下载。 三者的共同思想:发给浏览器的,应该是「此刻要执行的」,不是「库里存在的」。
12.2 大规模协作:依赖冲突的微观解剖¶
第 5 节的 React 升级例子值得再看一眼它的结构。单一代码库里, A 团队要 React 19、B 团队的组件只兼容 React 18——依赖是一个共享变量, 所有团队必须同时取值。可选的出路书里点了两个名字:module federation (让同一页面的不同部分独立部署、独立带依赖,细节在后续章)与 codemods (自动改写代码的工具,大规模升级时把「手工改两千处调用」变成「跑一个脚本」,后续章)。 两者都在 MEAP 之外,但它们要解决的问题在本章已经看得清清楚楚。19
12.3 依赖管理:四类事故的对策索引¶
把第 5 节的四类事故配上「忍者对策」,本章闭环:
| 事故 | 机制根因 | 对策(本章/后续章) |
|---|---|---|
| 小版本带破坏性变更 | 包作者没守 semver 约定 | 锁版本 + 升级前读 changelog;codemods 降迁移成本 |
| 同包多版本共存 | 依赖树的嵌套结构(第 3 章) | 理解 node_modules 结构,能提就提 |
| ESM/CJS 撞车 | 两套模块标准并存(后续章) | 知道你在写哪一种;构建工具配好互操作 |
| 供应链攻击 | 第三方代码在你机器上执行 | 装包前读源码(本章的忍者能力);lockfile 审 diff;后续章更多 |
最后一行是全章的落点:这门语言给你一种别的语言少有的防御——依赖的源码就在 node_modules 里躺着,读得懂 JavaScript 的人,才谈得上审计依赖。 这又把话题绕回本书的主题:语言功力本身就是工程能力。20
13. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| Atwood 定律与 10 天起源 | Chapter 1: JavaScript is everywhere | text/04-ch01-chapter-1-javascript-is-everywhere.txt:3(搜「Atwood's Law」) · :12(搜「10-day project」) |
| 三点语言差异 | 同上 | :18(搜「it's a trap」) · :50(搜「first-class objects」) |
| 运行时与引擎分层 | 同上 | :91(搜「runtimes, environments」) · :97(搜「just-in-time compilation」) |
| ECMAScript 标准化 | 同上 | :134(搜「ECMAScript Committee」) |
| transpiler 与 polyfill | 同上 | :151(搜「transpiler」) · :161(搜「polyfill, which is code」) · :168(搜「lookbehind assertions」) |
| 框架三分法 | 同上 | :181(搜「A framework is a library」) · :197(搜「ruled the web」) · :254(搜「routes HTTP requests」) · :287(搜「write once, run anywhere」) |
| 最佳实践三件套 | 同上 | :326(搜「flexible type system」) · :360(搜「The Good Parts」) · :401(搜「unit test」) |
| 性能与代码膨胀 | 同上 | :443(搜「code bloat」) |
| 协作与依赖管理 | 同上 | :472(搜「multiple teams」) · :498(搜「Dependency management」) · :511(搜「supply chain attack」) |
| 全章总结 | 同上 | :524(搜「Summary」) |
-
出处:「Chapter 1: JavaScript is everywhere」第 3–5 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:3,搜「Atwood's Law」)。这是 Jeff Atwood(Stack Overflow 联合创始人)的半开玩笑定律,原书用它开篇。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 18–26 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:22,搜「Competition between browser vendors」)。三条演化线:引擎竞争、ECMAScript 标准、Node.js 运行时,原书一一对应小节。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 45 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:45,搜「it's a trap」)。原文:「People often feel that if they know C# or Java, they already have a pretty solid understanding…But it's a trap!」 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 50–54 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:50,搜「first-class objects」)。原书列了一等对象的四项待遇:赋给变量、当参数传递、被别的函数创建、与任何对象共存。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 55–59 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:55,搜「Prototype-based object orientation」)。原书强调 class 关键字底下仍是原型,详细展开在第 9 章。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 60–64 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:60,搜「Single-threaded」)。单线程与回调/promise 的因果关系是原书明写的。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 66–69 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:66,搜「close relationship between objects and prototypes」)。原书把「对象与原型、函数与闭包」两对关系称作理解这门语言的核心。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 134–138 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:135,搜「Sun Microsystems' trademark」)。商标纠纷与 ECMAScript 命名由来。 ↩ -
出处:「Chapter 1: JavaScript is everywhere」第 91–131 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:91,搜「JavaScript runtimes and engines」)。运行时与引擎的分层、API 绑定的定义;「helpful to have some knowledge」见第 103–105 段。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 110–122 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:118,搜「jsdom」)。jsdom 与 WebContainers 的互相模拟及各自用途。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 202–224 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:205,搜「useState」)。React 计数器组件完整代码;虚拟 DOM 的机制见第 221–223 段。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 225–235 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:227,搜「own spin on the React paradigm」)。挑战者对 React 范式的变体关系与生态判据。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 249–267 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:257,搜「import express」)。Express 五行服务器示例。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 253–278 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:268,搜「Adonis」)。Adonis 的自带功能清单(认证、国际化、ORM)与 Keystone 的定位。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 287–310 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:290,搜「Instead of writing a Swift application」)。写一次处处跑的卖点;Electron/Ionic 与 React Native 的分化见第 293–307 段;Slack/Notion/Figma 与 Discord/Pinterest/Skype 的点名见第 300、307 段。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 401–418 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:406,搜「unit test verifies code's behavior in isolation」)。单元测试与端到端测试的定义、mock 与 fixture、框架名单(Vitest/Jest/Mocha;Playwright/Cypress)。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 419–433 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:424,搜「console.assert(condition, message)」)。console.assert 的语法与「No output / Emits」行为示例。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 443–470 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:446,搜「Search engines penalize slow pages」)。三笔账(排名、用户耐心、可度量的服务);「downloaded and parsed」见第 463–464 段。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 487–496 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:491,搜「module federation」)。module federation 与 codemods 的预告及其要解决的问题。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 516–521 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:519,搜「read the code for yourself」)。「加依赖之前能读源码」的忍者能力论断。 ↩↩ -
出处:「Chapter 1: JavaScript is everywhere」第 443–449 段(
text/04-ch01-chapter-1-javascript-is-everywhere.txt:462,搜「surefire recipe」)。「Taking the easy path at every step is a surefire recipe for sending a lot of unnecessary code to the browser」。 ↩