编程语言研究书库

JavaScript 基础 — 变量、数据、控制流、函数、数组、对象与错误处理

JavaScript 基础 — 变量、数据、控制流、函数、数组、对象与错误处理

这一章讲一件事:JavaScript 这门语言本身,从零教到能干活。 HTML 和 CSS 都不是编程语言——到这里,你第一次拿到一台真正的「计算机语言」: 它会存数据、会判断、会循环、会把代码打包复用、会组织复杂的结构、会优雅地摔倒。 原书这一章 4.9 万字符,是全书的重心;我们照原书的知识点全集讲,顺序不变、例子照用。 不需要任何编程基础。

1. 先看现象:网页「活了」是什么意思

前面十章,页面是死的:加载出来什么样,就永远什么样(除了链接跳转)。 JavaScript 登场之后,同样一个页面可以回应你了:按钮点了有反应、表单实时检查、内容不用刷新就更新。 这个「活」,本质上是程序在跑——而程序,就是这一章要学的这门语言写的。

书里给 JavaScript 的定义值得抄全:一门高级、动态、多范式的编程语言,主要用来在网页上创建交互和动态内容; 它支持面向对象、函数式、命令式三种写法,通常跑在浏览器里(客户端), 有了 Node.js 也能跑在服务器上1。一句一句拆:

  • 高级(high-level):你不用管内存和处理器,写「人话」;
  • 动态(dynamic):程序跑起来还能改自己(和 CSS 的「动态调整」不是一回事,这里指语言的类型在运行时才确定,见 §4);
  • 多范式(multi-paradigm):它不逼你只用一种编程风格——这个名词现在只需混个脸熟,§9 的类和函数会各露一手。

书里还收了这门语言的四个特点:代码是解释执行的(不需要先编译成别的形式);客户端和服务器端都能跑; 动态类型——变量不绑定特定类型,装数字的盒子之后能改装文字;能和 HTML/CSS 无缝集成2。

还有一个你会反复听见的生态问题:React、Angular、Vue.js 是什么?书里给了一张三家对照3:

名字出身与体量一句话记住它
ReactFacebook 出的库组件化:把界面拆成可复用的小块;用一个「虚拟 DOM」(内存里的树影子)只更新该变的部分,换性能
AngularGoogle 出的全家桶框架自带双向数据绑定、依赖注入、命令行工具;用 TypeScript 写,走大而全的企业应用路线
Vue.js独立的渐进式框架取两家之长、上手更平缓;数据一变界面自动跟着变;比 Angular 轻,好塞进已有项目

这三个名字现在只需「听过」:它们全都建立在本书的 DOM 和语言基础之上。 顺序上先地基后框架是对的——地基不稳学框架,框架会表现得像魔法。

2. 顶层全景:一张语言地图

  存东西    变量(let/const/var) + 数据类型(数字、字符串、布尔、数组、对象)
  判方向    条件(if / else if / else、switch)
  跑重复    循环(for、while、do-while;break/continue)
  打包复用  函数(function、参数、默认值、rest、return、作用域、提升)
  组数据    数组(增删改查、splice/slice)+ 对象与类(class、this、new)
  兜错误    try { … } catch (e) { … } finally { … }

  图说:六格就是本章六到十一节——一门语言的最小全集,每格都撑得起后面 DOM 章的一整块。

3. 语法规矩与保留字

先立规矩,再写代码。书里点了四条4:

大小写敏感。 Greeting 和 greeting 是两个不同的变量5。这一条每年坑几万个新手—— 报错「xxx is not defined」时,先查大小写。

语句以分号结尾。 let firstName = "Alice"; 末尾的分号,书里说严格讲不强制, 但专业写法都加,尤其在团队和严格检查规则下6。约定俗成:加。

代码块用花括号 {}。 函数体、if 体、循环体都是块——块是「这段代码是一伙的」的记号7。

注释。 单行 // 这样,多行 /* 这样 */8。注释是写给「三个月后的自己」的, 书里的代码注释率很高,照学。

保留字(reserved words,关键字):语言自己占用的词——if、else、for、let、 class、return、new……不能拿来做变量名或函数名9。书里按用途列了六大类表: 控制语句、循环、函数、变量声明、类与对象、异步(Promise/async),外加杂项(new、delete、typeof、try、catch、finally、throw 等)。 这张表不用背——写多了自然记得;现在的用处是知道「为什么有的词 IDE 里会变颜色」。

不过这张表的结构值得花一分钟看:书里把保留字按用途分了六类,正好露出这门语言有哪些器官10:

类别成员(摘)管什么
控制语句if else switch case default分支:走哪条路
循环for while do break continue重复:跑多少圈、何时停
函数function return yield打包与返回(yield 属生成器,本书不讲,混脸熟)
变量声明var let const造盒子(§4)
类与对象class extends super this图纸与实例(§12)
异步async await等一会儿再拿结果(本书不讲,混脸熟)
杂项new delete typeof instanceof void try catch finally throw造对象、查类型、错误处理(§13)

4. 变量:let 和 const 的时代,var 是遗产

变量(variable)是「存一个值、起个名字、以后用名字取」的机制。书里给的声明写法11:

let firstName = "Alice";   // 变量:可以换值
const pi = 3.14;           // 常量:声明时必须赋值,之后不能换

let 和 const 都是 ES6(2015 年发布的那代 JavaScript 标准,ECMAScript 6 的简称)引入的; 之前的老写法是 var12。书里给的换代理由只有一句但很关键:let 有块级作用域(block-scoping)12。

什么是块级作用域?花括号 {} 里用 let 声明的变量,出了花括号就不存在:

if (true) {
    let inside = "只在括号里活着";
}
console.log(inside);   // 报错:inside is not defined(④ 类常识补充:var 声明的则会漏出括号外)

const 是「更严格的 let」:声明时必须给值,之后不能再赋值。注意「不能换绑」不等于「内容不能变」—— const 的数组你照样能往里加元素(数组本身这个盒子没变),只是不能把这个变量指到另一个盒子去。 这一行的现行默认:默认用 const,确实要换值才用 let,var 只在读老代码时见到。

判断(我们的,不是书里的): var 的活教材价值在「提升」(§8 末)和「无块级作用域」两个坑上。 书里对 var 只给了「old syntax」一句注释12,这是对的教学取舍; 但你要知道:读懂 2015 年前的老代码、以及某些「var 提升」面试题,var 还得认得。 如果错,会错在: 如果未来某版标准彻底移除 var(目前没有计划),「var 是遗产」的判断就要改成「var 已消失」—— 但 2026 年的现实是它仍被浏览器全量支持。

5. 数据类型之一:数字与数学

JavaScript 的数字只有一个 Number 类型,整数和小数(浮点数)不分家:10 和 3.5 是同一种东西13。 运算符一览(书里的表14):+ - * / %,以及自增 ++、自减 --(x++ = x 加 1 再存回 x)。 % 是取余——10 % 3 得 1,判奇偶的标配(x % 2 == 0 即偶数)。

数学函数集中在 Math 对象里(对象是什么 §9 讲,这里先当「工具箱」用)15:

调用结果(书中例子)
Math.sqrt(25)5(平方根)
Math.pow(2, 3)8(2 的 3 次方)
Math.round(4.6)5(四舍五入)
Math.floor(4.9)4(向下取整)
Math.ceil(4.1)5(向上取整)
Math.random()0 到 1 之间的随机小数
Number.isInteger(10)true(是否整数)
Number.isNaN(10 / 'hello')true(是否「非数字」)

最后一个值得多看一眼:10 / 'hello' 在 JavaScript 里不报错,结果是 NaN(Not a Number)。 JavaScript 的数字运算对「算不出来」的回应是给你这个特殊值,而不是崩溃—— 它的「动态」性格第一次露脸。

6. 数据类型之二:字符串与它的工具箱

字符串(string)是文字。书里的三个引号规矩16:双引号、单引号完全等价;反引号 ``` 是增强版—— 它支持模板字符串(template literal):用 ${} 把变量嵌进字符串17:

let name = "John";
let message = `Hello, ${name}!`;   // "Hello, John!"

反引号还支持真正的换行——普通引号里的字符串换行要写 \n(转义字符)。 转义序列(escape sequences)就是「反斜杠 + 一个字母 = 一个打不出来的字符」18: \n 换行、\t 制表符、\" 双引号、\\ 反斜杠本身、\u2764 Unicode 字符(一颗心)。 为什么需要 \":字符串本身用双引号包住,字符串里的双引号必须「转义」成 \" 才不会被当成字符串的终点。

字符串的两个身份特征,书里讲得清楚:

其一,不可变(immutable)。 字符串一旦造出来就不能改;所有字符串方法都是「基于原串造一个新串」, 原串纹丝不动16。text.toUpperCase() 返回大写版,text 自己还是原样。

其二,有索引(index)。 从 0 开始数:"user@example.com" 的第 0 位是 u,第 4 位是 @19。 email[2] 取第 2 位;.length 取总长(含空格标点)。

主线例子(上):从邮箱里切出用户名

这一章的主线例子,是书里那个「从邮箱地址解析出用户名」的完整推演,每一步都有具体的数和状态19:

  输入:   let email = "user@example.com";
  第 1 步:找 @ 的位置
          email.indexOf("@")
          → 逐位扫描:u(0) s(1) e(2) r(3) @(4)…
          → 返回 4
  第 2 步:切片
          email.slice(0, 4)      ← slice(起点, 终点),终点不算在内
          → 取出第 0、1、2、3 位 → "user"
  第 3 步:得到结果
          let username = "user"

  图说:indexOf 回答“在哪儿”,slice 回答“从哪儿到哪儿切一刀”;
       两个方法拼起来,就是字符串处理的基本动作:定位 → 提取。

这本书的讲法(给出一整串中间状态)正是我们主张的「每步旁边有具体的数」—— indexOf 返回 4、slice 取 [0,4) 半开区间,都是能当场验算的。

常用字符串方法(书里的工具箱)

方法干什么书中例子
.toUpperCase() / .toLowerCase()大小写转换"This is Fun!" → THIS IS FUN! / this is fun!
.slice(start, end)切一段(终点不含)见主线例子
.indexOf(x)x 第一次出现的位置"user@example.com" 里 @ → 4
.replace(旧, 新)替换第一个匹配"This is Java!" → "This is JavaScript!"
.split(分隔符)按分隔符切成数组"apple,banana,grape".split(",") → ["apple","banana","grape"]
.length字符总数属性,不是方法,没有括号

.split 是字符串通往数组的桥——下一节的主角马上登场。

7. 布尔与逻辑运算

布尔(Boolean)只有两个值:true 和 false,是「判断」这种思维的数据形态20。 三个逻辑运算符:

运算符名字规则
&&与(AND)两边都 true 才 true
||或(OR)有一边 true 就 true
!非(NOT)取反:true 变 false

优先级(先算谁)书里给了顺序:! 高于 && 高于 ||21。 a || b && c 先算 b && c;想改变就用括号 (a || b) && c。 括号的正式身份是「我这里的优先级我说了算」,和数学里一样。

顺带把全书反复用到的比较运算补齐:== 等于、!= 不等、> < >= <=。 (更严格的 ===「值和类型都相同」书里只在章末习题出现——这一行的默认是用 === 不用 ==, ④ 类补充:"5" == 5 为 true 而 "5" === 5 为 false,前者会自动转换类型,坑多。)

8. 输出与 HTML 集成:程序怎么跑起来

写了代码,怎么看结果?书里给了两条路:

console.log(…):把内容打印到浏览器的开发者工具控制台(第 03 章那台 X 光机的 Console 面板), 不动页面本身——查变量值、追错误、看代码怎么跑的标配22。学语言阶段,你的 90% 输出都走这里。

document.write(…):直接往页面里写内容。 书里给了郑重警告:页面加载完再调用它,会覆盖整页23。 教学用可以,真实项目别碰——第 12 章的 DOM 方法才是改页面的正规军。

代码放哪?书里两条规矩24:

<!-- 规矩一:<script> 放在 body 的最末尾(</body> 之前) -->
<script>
    …你的代码…
</script>

<!-- 规矩二:必须放 <head> 里的话,加 defer -->
<script src="script.js" defer></script>

为什么? 第 01 章的渲染链条还记得吗:浏览器边读 HTML 边建 DOM 树,碰到 <script> 会停下来先执行。 脚本放前面,它执行时后面的 DOM 还没建出来——第 13 章会现场抓一个这种 bug。 defer 的意思是「先别跑,等 HTML 全部读完再跑」,效果等于把脚本挪到了 body 末尾,还能让它留在 head 里。 外部文件用 <script src="…"> 引入,和 CSS 的 <link> 对仗。

9. 控制流:程序的方向盘

控制流(flow control)是「语句按什么顺序执行」。默认从上到下逐行执行; 三种结构可以改变这个顺序。

条件:if / else 与 switch

if 是「条件成立才执行这块」;if...else 是「成立走这边,不成立走那边」25:

let number = 10;
if (number % 2 == 0) {
    console.log("The number is even.");   // 走这条:10 % 2 == 0 为 true
} else {
    console.log("The number is odd.");
}

switch 是「一个变量对多个值」的多路选择,书里给的骨架26:

switch (day) {
    case "Monday":
        console.log("Start of the workweek.");
        break;                       // ← 关键:匹配后 break,否则会继续往下“穿透”
    case "Friday":
        console.log("Weekend is coming!");
        break;
    default:                         // 一个都没匹配上时兜底
        console.log("It's a regular weekday.");
}

break 是 switch 的灵魂:没有它,匹配了一个 case 后会继续执行后面所有 case(这叫「穿透」, 有时候故意利用,但入门阶段默认每个 case 都 break)。什么时候 if、什么时候 switch? 两三个分支用 if,一个变量对一整排固定值用 switch——后者更清晰。

循环:三种,各管一类重复

循环的三要素,书里拆得很清楚:初始化(造一个计数器)、条件(真就继续)、更新(每圈改计数器)27。 三种循环的分工:

循环什么时候用书中例子
for循环几圈已知for (let i = 1; i <= 5; i++) console.log(i); 打印 1–5
while条件不满足就停,可能一圈都不跑倒计时:while (count > 0) { … count--; }
do...while至少跑一圈再判断do { … i++; } while (i <= 5);

for 的括号里三格用分号隔开:初始化 let i = 1;条件 i <= 5;更新 i++(每圈结束把 i 加 1)。 执行轨迹逐圈走一遍(主线例子的节奏):i=1 满足 → 打印 1 → i 变 2 → … → i=5 打印 → i 变 6 → 条件不成立,循环结束。 五圈,计数器从 1 走到 6——「计数器最终会越过条件边界一格」,这是所有 for 循环的共同句读。

break 提前跳出整个循环、continue 跳过这一圈进下一圈——第 07 章保留字表里的两位,语法直观,不展开。

10. 函数:打包与复用

函数(function)是「打包好、能反复用的一块代码」。书里给的定义里有一对词要钉住: 参数(parameters)是函数定义里的输入名,实参(arguments)是调用时真正传进去的值28:

function add(a, b) {      // a、b 是参数
    return a + b;
}
let result = add(5, 3);   // 5、3 是实参;result 得到 8

return 干了三件事:给出返回值、立刻结束函数(return 之后的代码不执行)、 没写 return 的函数默认返回 undefined29。书上 add(5,3) 的推演:5+3=8,return 8, 8 赋给 result——一行调用,三步状态。

三种参数形态,书里各给一例:

必填参数:少传了不会报错,但缺的参数是 undefined,multiply(4) 里 y 是 undefined, 乘出来是 NaN30——JavaScript 的「动态」性格再次露脸:它不拦你,给你个怪结果。

默认参数(ES6):function greet(name = "Guest") { … },调用时没传或传了 undefined, 就用默认值31。greet() → "Hello, Guest!";greet("Alice") → "Hello, Alice!"。

rest 参数:function sum(...numbers) { … },... 把传进来的所有实参收成一个数组32:

function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4, 5);   // numbers = [1,2,3,4,5] → 15
sum(10, 20);          // numbers = [10,20]     → 30

(例子里的 reduce 是数组方法,意思是「把数组滚成一个值」——它第一次出现,知道大概即可, 数组方法的本体在 §11。)同一个函数,五个参数和两个参数都接得住——参数个数从「写死」变成「弹性」。

作用域:变量的能见度

作用域(scope)是「这个变量在哪段代码里看得见」。书里两格规则33:

  • 函数里声明的变量是局部的:只在该函数内可见,外面碰不到;
  • 函数外声明的是全局的:哪里都看得见(函数里面也能读)。
let globalVar = "I am global";          // 全局
function showGlobal() {
    return globalVar;                   // 函数内读全局:可以
}
function exampleFunction() {
    let localVar = "I am local";        // 局部
    return localVar;
}
console.log(localVar);   // 报错:函数外的代码不认这个局部变量

作用域的存在理由:防止「哪都能改」的失控。函数是自包含的小机器——喂给它输入(参数)、 它吐给你输出(return),中间用多少临时变量都不污染外面。写函数的好习惯是:能用局部就不用全局。

提升(hoisting):一个「坑」级别的机制

提升是 JavaScript 的一个古怪行为:函数和变量的声明,在代码执行前会被「挪到」其作用域的顶部34。 所以这段代码能跑:

hello();                    // 调用写在声明前面
function hello() {
    return "Hello, world!";
}

书里的解释模型是:JavaScript 内部先把声明挪上去,再按挪完的版本执行34。 但「挪」有三种待遇,必须分清(书里点了一半,我们补全):

声明方式提升后拿到什么声明前使用会怎样
function 声明整个函数正常调用(如上例)
var 变量名字(undefined 值)不报错但值是 undefined(怪结果)
let / const名字在「暂时性死区」直接报错

入门阶段的实操建议很朴素:把函数声明写在调用前面,把这个机制当作「读懂报错」的知识而不是「利用」的技巧。 (读老代码时会见到「依赖提升」的写法——认识它,别学它。)

书里还补了一个关键区分:「函数声明」和「函数表达式」的提升待遇不一样。 函数表达式是「把函数赋给一个变量」的写法——let hello = function() { … }; 这种写法只有变量名被提升,函数体留在原地,所以在赋值完成之前调用它,拿到的是 undefined 而不是函数35。 这解释了为什么「先写调用后写声明」只对 function xxx(){} 那种老派写法安全。

11. 数组:一排水槽

数组(array)是「一个变量名,装一排值,按编号取」。书里定义里那个词要接住: 索引(indexed)——每个元素有固定位置,从 0 开始数36。

let fruits = ["Apple", "Banana", "Cherry"];
//  索引:        0         1          2
fruits[1];            // "Banana"
fruits[1] = "Blueberry";   // 改:索引 1 处换成 Blueberry

主线例子(下):fruits 数组的完整一生

这一章的主线例子下半段,是 fruits 数组从生到死的全流程——书里把每步之后的数组状态都画了出来, 我们照抄这个节奏:

  出生:   let fruits = ["Apple", "Banana", "Cherry"];
              索引   0        1         2
  改:     fruits[1] = "Blueberry";     → [Apple, Blueberry, Cherry]
  尾加:   fruits.push("Mango");        → [Apple, Blueberry, Cherry, Mango]
  头加:   fruits.unshift("Strawberry");→ [Strawberry, Apple, Blueberry, Cherry, Mango]
  尾删:   fruits.pop();                → 返回 "Mango";数组退回 4 个
  头删:   fruits.shift();              → 返回 "Strawberry";数组 = [Apple, Blueberry, Cherry]
  总长:   fruits.length                → 3
  遍历:   for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]); }
          → i=0 打 Apple;i=1 打 Blueberry;i=2 打 Cherry;i=3 条件失败,停

  图说:push/pop 管尾部,unshift/shift 管头部;方法名都是“动作”,返回值是“被拿走的那一个”。

四个增删方法的记忆法:push/pop 是尾部进出(像栈),unshift/shift 是头部进出; pop/shift 会「返回」被删掉那个元素(可以接住用),push/unshift 返回的是新长度。 length 则让 for 循环的边界「数组多长就转多少圈」,数组内容变了循环自动跟着变。

splice 与 slice:一对必须分开的孪生

书里用了两个对照表来讲这对方法,分界就一条:改不改原数组3738:

let fruits = ["Apple", "Banana", "Cherry", "Mango"];

let removed = fruits.splice(1, 2);
//      从索引 1 开始,删掉 2 个     → removed = ["Banana", "Cherry"]
//                                    fruits 变成 ["Apple", "Mango"]  ← 原数组被改了!

let extracted = fruits.slice(1, 3);
//       从索引 1 切到 3(不含 3)   → extracted = [索引1, 索引2]
//                                    原数组不动,拿到的是新数组
  splice(起点, 个数):挖掉,原数组受伤,挖走的部分作为返回值   ← 手术
  slice(起点, 终点): 复印,原数组无恙,复印件是新的数组       ← 复印

背法:splice 带「p」像「paperclip(回形针)」会留下孔——原数组被改了; slice 就是「切一片下来看看」。两个方法还都在字符串上有个同名亲戚(§6 的 slice、replace 家族)—— 数组版切元素、字符串版切字符,语义一致。

12. 对象与类:把数据和行为装进一个盒子

对象(object)是「一组相关的属性和方法的集合」;类(class)是造对象的图纸39。 书里给的 User 类,是这一节的主线:

class User {
    constructor(username, email, role) {   // 构造器:造对象时自动运行,初始化属性
        this.username = username;
        this.email = email;
        this.role = role;
    }
    updateRole(newRole) {                  // 方法:这个类的对象会做的事
        this.role = newRole;
    }
    getProfile() {
        return `User: ${this.username}, Email: ${this.email}, Role: ${this.role}`;
    }
}

let adminUser = new User("AliceJohnson", "alice@company.com", "Admin");

逐词过一遍(全是会出门撞见的词):

  • constructor(构造器):new 造对象时自动执行的那个方法,负责把传进来的值装进新对象;
  • this:「当前这个对象」。构造器里的 this.username = username 就是「把我这个新对象的 username 属性,设成传进来的值」;
  • new:按图纸开工——new User(…) 造出一个 User 的实例(instance),三个实参进构造器;
  • 点语法(dot notation):adminUser.updateRole("Super Admin") = 「这个对象的 updateRole 方法,传这个参数」40;
  • 属性 vs 方法:属性是数据(username),方法是行为(getProfile())。

用类的理由,书里给了:建模真实世界的实体、让代码有组织、好维护39。 对照 §11 的数组:数组是「一排同类的东西」,对象是「一个东西的多方面」—— 菜单用数组(一排菜),一道菜用对象(菜名、价格、是否招牌)。 这两个容器加函数,就是 JavaScript 组织数据的全部基础。

判断(我们的,不是书里的): 本章只教了 class 语法,没教「对象字面量」 (let user = { name: "Alice", role: "Admin" })——这是 JavaScript 里使用频率不低于 class 的写法, 第 13 章存 localStorage 的数据就是它。书里 class 先行是教学顺序(从「图纸」到「实例」比较顺), 但你自己动手时,简单数据优先用对象字面量,class 留给「要造很多个同类对象、带方法」的场景。 如果错,会错在: 面向对象的阵营里(以及 Angular、旧企业框架),class 是主角不是配角—— 「简单数据用字面量」是这一行主流库(React 生态)的口味,不是语言的规定。

13. 错误处理:优雅地摔倒

程序会出错:除以零、读不存在的变量、类型错乱。默认行为是整个程序崩掉——页面卡死、用户流失。 try...catch 是兜底的网:可能出问题的代码放进 try,真出了错,流程立刻跳进 catch, 程序不崩41:

function divideNumbers(a, b) {
    try {
        if (b == 0) {
            throw new Error("Cannot divide by zero.");   // 自己制造一个错误
        }
        return a / b;
    } catch (error) {
        return error.message;                            // 接住,把错误信息当结果返回
    }
}
divideNumbers(8, 0);   // 走 catch:返回 "Cannot divide by zero."
divideNumbers(8, 2);   // 正常:返回 4

三件套的完整形态是 try / catch / finally:finally 可选,无论出没出错都执行—— 放「收尾工作」(关连接、复位状态)的地方。

三个关键词的句读:try 圈出「危险区」;throw 主动扔出一个错误(new Error("…") 造一个); catch (error) 接住,error.message 是它带的说明。书里还点了一排内置错误类型: ReferenceError(用了不存在的变量)、TypeError(类型不对,如对数字调用字符串方法)、 SyntaxError(代码本身写错)、RangeError(数值越界)42——catch 里可以按类型区别对待。

边界要说清: try...catch 兜的是「运行时」错误(跑着跑着出的错);代码本身的语法错误(少个括号), 整个脚本都不会运行,catch 也救不了——那是「写的时候」就该被编辑器拦下的错。

14. 作者的判断与证据

书内作为事实给出的: 全部语言机制(变量、类型、方法、控制流、函数、数组、类、try...catch)的定义与行为, 引用已随文给出。

作者的取舍,值得意识到: 这一章在「语言最小全集」上的取舍相当克制—— 没有碰 == vs ===(只在习题里)、没有正则(只在表单章的 pattern 属性)、没有日期对象、 没有 map/filter(reduce 倒是露了一面)、没有异步。最小全集的好处是不会噎死初学者; 代价是离「能写真实功能」还差 DOM(第 12 章)和一点点异步常识(总纲覆盖表已标为不覆盖)。

一处要当心的表述: 书中有些代码片段的排版在转码中受损(如字符串里混入表情符号的占位符),按上下文理解即可—— 语义都是标准行为,不影响教学。

15. 边界与局限

  • 异步整个缺席。 Promise、async/await 只在保留字表露名;而真实网页的请求数据、定时器、动画全靠异步—— 学完本书想接第 13 章之后的现实世界,异步是第一门必修课。
  • 对象字面量没教(见 §12 判断块);map/filter/find 这组高频数组方法没教。
  • ==/=== 的区别只在章末习题,但这个坑日常就踩——我们在 §7 补了默认值建议。
  • 没有正则、没有 Date、没有 JSON(JSON 要到第 13 章才实际用到,本书未解释)。

16. 可带走的

全章两条主线例子,一行各写完: 邮箱解析 = indexOf 定位 @ 在 4 → slice(0,4) 切出 "user"; fruits 数组 = push 尾加 → unshift 头加 → pop 尾删 → shift 头删 → length 数长度 → for 按索引遍历。

  1. JavaScript:高级、动态、多范式;一门语言,浏览器和服务器(Node.js)都跑1;
  2. 大小写敏感;分号结尾;花括号成块;// 与 /* */ 注释5;
  3. 默认 const,要换值用 let;var 是遗产12;let/const 有块级作用域;
  4. 数字只有一个类型;% 取余;Math 工具箱(sqrt/pow/round/floor/ceil/random);
  5. 字符串不可变、有 0 起索引;反引号 + ${} 是模板字符串;\n \" 等转义序列;
  6. 字符串五件套:.length、.toUpperCase()、.slice()、.indexOf()、.replace()、.split();
  7. 逻辑运算 ! > && > ||;比较默认用 ===(④ 类建议);
  8. console.log 打到控制台(调试标配);脚本放 body 末尾,或 head 里加 defer24;
  9. switch 别忘了 break;for 三格「初始化;条件;更新」;do...while 至少跑一圈27;
  10. 函数 = 参数(定义)与实参(调用)之别;return 即出结果即结束;默认参数 =、rest 参数 ...;
  11. 作用域:局部变量不出函数;提升只完整作用于 function 声明,let/const 声明前使用直接报错34;
  12. 数组从 0 数;push/pop 尾部、unshift/shift 头部;splice 改原数组,slice 不改3738;
  13. 类 = 图纸;new 造实例;this 是当前对象;构造器装初始值;点语法调方法39;
  14. try 圈危险区、throw 扔错、catch 接住、finally 必执行;内置错误类型有 ReferenceError/TypeError 等42。

17. 原文地图

主题原书章原文位置
语言的定义与特点Introduction to JavaScripttext/17-fm-introduction.txt:41(搜「high-level, dynamic, multi-paradigm」)
大小写敏感Introduction to JavaScripttext/17-fm-introduction.txt:65(搜「case-sensitive」)
保留字与六大类关键字表Introduction to JavaScripttext/17-fm-introduction.txt:89(搜「Keywords are reserved words」)
let/const 取代 var 与块级作用域Introduction to JavaScripttext/17-fm-introduction.txt:397(搜「let keyword is now preferred」)
单一 Number 类型Introduction to JavaScripttext/17-fm-introduction.txt:411(搜「single Number type」)
字符串不可变与三种引号Introduction to JavaScripttext/17-fm-introduction.txt:533(搜「They are immutable」)
模板字符串Introduction to JavaScripttext/17-fm-introduction.txt:549(搜「Template literal allows」)
转义序列Introduction to JavaScripttext/17-fm-introduction.txt:555(搜「Escape sequences are special」)
邮箱解析(@ 在索引 4)Introduction to JavaScripttext/17-fm-introduction.txt:801(搜「at index 4」)
逻辑运算优先级Introduction to JavaScripttext/17-fm-introduction.txt:921(搜「evaluated in this order」)
console.log 与 document.writeIntroduction to JavaScripttext/17-fm-introduction.txt:951(搜「sends messages to the browser」) · text/17-fm-introduction.txt:949(搜「overwrite the entire page」)
script 位置与 deferIntroduction to JavaScripttext/17-fm-introduction.txt:957(搜「end of <body>」)
switch 与 break/defaultIntroduction to JavaScripttext/17-fm-introduction.txt:1043(搜「compared against multiple values」)
循环三要素Introduction to JavaScripttext/17-fm-introduction.txt:1101(搜「three main components」)
函数定义:参数与实参Introduction to JavaScripttext/17-fm-introduction.txt:1177(搜「block of reusable code」)
默认参数与 rest 参数Introduction to JavaScripttext/17-fm-introduction.txt:1219(搜「fallback value」) · text/17-fm-introduction.txt:1231(搜「indefinite number of arguments」)
returnIntroduction to JavaScripttext/17-fm-introduction.txt:1245(搜「used to return a value」)
函数作用域Introduction to JavaScripttext/17-fm-introduction.txt:1269(搜「local scope」)
提升Introduction to JavaScripttext/17-fm-introduction.txt:1295(搜「moved to the top of their scope」)
数组与索引Introduction to JavaScripttext/17-fm-introduction.txt:1319(搜「data structures」)
push/unshift/pop/shiftIntroduction to JavaScripttext/17-fm-introduction.txt:1373(搜「push()」) · text/17-fm-introduction.txt:1397(搜「unshift() to add elements to the beginning」)
splice 改原数组Introduction to JavaScripttext/17-fm-introduction.txt:1497(搜「directly modifying the original array」)
slice 不改原数组Introduction to JavaScripttext/17-fm-introduction.txt:1535(搜「without altering the original」)
类、构造器、this、newIntroduction to JavaScripttext/17-fm-introduction.txt:1565(搜「blueprint for creating objects」) · text/17-fm-introduction.txt:1601(搜「refers to the object」)
try...catchIntroduction to JavaScripttext/17-fm-introduction.txt:1621(搜「without crashing the whole program」)
内置错误类型Introduction to JavaScripttext/17-fm-introduction.txt:1663(搜「built-in error types」)
语言四特点Introduction to JavaScripttext/17-fm-introduction.txt:53(搜「Key features of JavaScript」)
React/Angular/Vue 三家对照Introduction to JavaScripttext/17-fm-introduction.txt:47(搜「component-based architecture」) · text/17-fm-introduction.txt:49(搜「two-way data binding」) · text/17-fm-introduction.txt:51(搜「progressive framework」)
保留字六分类表Introduction to JavaScripttext/17-fm-introduction.txt:89(搜「Keywords are reserved words」)
函数表达式与提升Introduction to JavaScripttext/17-fm-introduction.txt:1315(搜「function expressions」)

Footnotes

  1. 出处:「Introduction to JavaScript」第 41 段(text/17-fm-introduction.txt:41,搜「high-level, dynamic, multi-paradigm」)。原文对「高级、动态、多范式」和 Node.js 使 JavaScript 能上服务器作了完整陈述。 ↩ ↩2

  2. 出处:「Introduction to JavaScript」第 53–61 段(text/17-fm-introduction.txt:53,搜「Key features of JavaScript」;:55,搜「interpreted and does not require」)。四个特点:解释执行不需编译、客户端与服务器端皆可、动态类型、与 HTML/CSS 无缝集成。 ↩

  3. 出处:「Introduction to JavaScript」第 45–51 段(text/17-fm-introduction.txt:47,搜「component-based architecture」;:49,搜「two-way data binding」;:51,搜「progressive framework」)。三家定位分别是库、全家桶框架、渐进式框架。 ↩

  4. 出处:「Introduction to JavaScript」第 63–85 段(text/17-fm-introduction.txt:65,搜「case-sensitive」;:69,搜「terminated with a semicolon」;:71,搜「curly braces」;:79,搜「single line comment」)。 ↩

  5. 出处:「Introduction to JavaScript」第 65 段(text/17-fm-introduction.txt:65,搜「case-sensitive」)。原文:「the variable Greeting is not the same as the variable greeting.」 ↩ ↩2

  6. 出处:「Introduction to JavaScript」第 67 段(text/17-fm-introduction.txt:67,搜「terminated with a semicolon」)。 ↩

  7. 出处:「Introduction to JavaScript」第 71 段(text/17-fm-introduction.txt:71,搜「enclosed in curly braces」)。 ↩

  8. 出处:「Introduction to JavaScript」第 79–85 段(text/17-fm-introduction.txt:79,搜「double slash」)。 ↩

  9. 出处:「Introduction to JavaScript」第 89 段(text/17-fm-introduction.txt:89,搜「Keywords are reserved words」)。原文:「they cannot be used as variable names, function names, or identifiers.」 ↩

  10. 出处:「Introduction to JavaScript」第 89–391 段(text/17-fm-introduction.txt:89,搜「Keywords are reserved words」)。六张分类表(控制语句、循环、函数、变量声明、类与对象、异步与杂项)依次见第 101、153、197、229、261、299、325 段起的各表。 ↩

  11. 出处:「Introduction to JavaScript」第 395–403 段(text/17-fm-introduction.txt:397,搜「let keyword is now preferred」;:401,搜「const is used to declare constants」)。 ↩

  12. 出处:「Introduction to JavaScript」第 397 段(text/17-fm-introduction.txt:397,搜「let keyword is now preferred」)。原文:「Traditionally, this was done using the var keyword. However, with the introduction of ES6, the let keyword is now preferred... due to its block-scoping feature.」 ↩ ↩2 ↩3 ↩4

  13. 出处:「Introduction to JavaScript」第 411 段(text/17-fm-introduction.txt:411,搜「single Number type」)。 ↩

  14. 出处:「Introduction to JavaScript」第 419–467 段(text/17-fm-introduction.txt:427,搜「Increment」;:451,搜「Modulus」)。 ↩

  15. 出处:「Introduction to JavaScript」第 473–529 段(text/17-fm-introduction.txt:481,搜「Math.sqrt」;:491,搜「Math.pow」;:499,搜「Math.round」;:511,搜「Math.floor」;:519,搜「Math.ceil」;:527,搜「Math.random」)。 ↩

  16. 出处:「Introduction to JavaScript」第 533 段(text/17-fm-introduction.txt:533,搜「They are immutable」)。原文:「once a string is created, it cannot be changed, but methods can be used to generate new strings based on modifications.」 ↩ ↩2

  17. 出处:「Introduction to JavaScript」第 549–553 段(text/17-fm-introduction.txt:549,搜「Template literal allows」)。 ↩

  18. 出处:「Introduction to JavaScript」第 555 段(text/17-fm-introduction.txt:555,搜「Escape sequences are special」)。 ↩

  19. 出处:「Introduction to JavaScript」第 689–693 段(text/17-fm-introduction.txt:693,搜「characters are indexed starting from 0」)与第 795–809 段(text/17-fm-introduction.txt:801,搜「at index 4」)。 ↩ ↩2

  20. 出处:「Introduction to JavaScript」第 889–895 段(text/17-fm-introduction.txt:891,搜「AND」;:893,搜「OR」;:895,搜「NOT」)。 ↩

  21. 出处:「Introduction to JavaScript」第 921–927 段(text/17-fm-introduction.txt:921,搜「evaluated in this order」;:923,搜「NOT」)。 ↩

  22. 出处:「Introduction to JavaScript」第 951 段(text/17-fm-introduction.txt:951,搜「sends messages to the browser」)。 ↩

  23. 出处:「Introduction to JavaScript」第 949 段(text/17-fm-introduction.txt:949,搜「overwrite the entire page」)。 ↩

  24. 出处:「Introduction to JavaScript」第 957 段(text/17-fm-introduction.txt:957,搜「end of <body>」)。原文:「Place <script> at the end of <body> for best performance and to avoid errors. If the script must be in <head>, use the defer keyword.」 ↩ ↩2

  25. 出处:「Introduction to JavaScript」第 995–1039 段(text/17-fm-introduction.txt:1009,搜「The number is positive」;:1031,搜「The number is even」)。 ↩

  26. 出处:「Introduction to JavaScript」第 1043 段(text/17-fm-introduction.txt:1043,搜「compared against multiple values」)。原文:「The break statement stops execution once a match is found, and the default case runs if no match is found.」 ↩

  27. 出处:「Introduction to JavaScript」第 1101–1105 段(text/17-fm-introduction.txt:1101,搜「three main components」)。 ↩ ↩2

  28. 出处:「Introduction to JavaScript」第 1177 段(text/17-fm-introduction.txt:1177,搜「block of reusable code」)。原文:「The inputs defined in the function are called parameters, and the actual values passed to the function are called arguments.」 ↩

  29. 出处:「Introduction to JavaScript」第 1245–1247 段(text/17-fm-introduction.txt:1245,搜「used to return a value」;:1247,搜「stops executing immediately」)。 ↩

  30. 出处:「Introduction to JavaScript」第 1207–1217 段(text/17-fm-introduction.txt:1215,搜「product1 is 20」;:1217,搜「y is undefined」)。 ↩

  31. 出处:「Introduction to JavaScript」第 1219–1229 段(text/17-fm-introduction.txt:1219,搜「fallback value」;:1229,搜「default used」)。 ↩

  32. 出处:「Introduction to JavaScript」第 1231–1241 段(text/17-fm-introduction.txt:1231,搜「indefinite number of arguments」;:1239,搜「total1 is 15」)。 ↩

  33. 出处:「Introduction to JavaScript」第 1269–1291 段(text/17-fm-introduction.txt:1269,搜「local scope」;:1283,搜「I am global」)。 ↩

  34. 出处:「Introduction to JavaScript」第 1295–1315 段(text/17-fm-introduction.txt:1295,搜「moved to the top of their scope」;:1315,搜「only function declarations are fully hoisted」)。 ↩ ↩2 ↩3

  35. 出处:「Introduction to JavaScript」第 1315 段(text/17-fm-introduction.txt:1315,搜「does not apply the same way to function expressions」)。原文:「If you assign a function to a variable (using var, let, or const), only the variable is hoisted, not the function itself.」 ↩

  36. 出处:「Introduction to JavaScript」第 1319 段(text/17-fm-introduction.txt:1319,搜「data structures」)。原文:「Arrays are indexed, meaning each element has a specific position.」 ↩

  37. 出处:「Introduction to JavaScript」第 1497–1533 段(text/17-fm-introduction.txt:1497,搜「directly modifying the original array」;:1503,搜「["Banana", "Cherry"]」;:1523,搜「["Apple", "Mango"]」)。 ↩ ↩2

  38. 出处:「Introduction to JavaScript」第 1535–1561 段(text/17-fm-introduction.txt:1535,搜「without altering the original」;:1561,搜「remains unchanged」)。 ↩ ↩2

  39. 出处:「Introduction to JavaScript」第 1565–1605 段(text/17-fm-introduction.txt:1565,搜「blueprint for creating objects」;:1601,搜「refers to the object」;:1607,搜「new User」)。 ↩ ↩2 ↩3

  40. 出处:「Introduction to JavaScript」第 1611–1617 段(text/17-fm-introduction.txt:1611,搜「dot notation」)。 ↩

  41. 出处:「Introduction to JavaScript」第 1621–1647 段(text/17-fm-introduction.txt:1621,搜「without crashing the whole program」;:1637,搜「jumps to the catch block」;:1647,搜「regardless of whether an error was thrown」)。 ↩

  42. 出处:「Introduction to JavaScript」第 1663 段(text/17-fm-introduction.txt:1663,搜「built-in error types」)。 ↩ ↩2

On this page