学习指南:为什么、怎么学、学到什么
JavaScript(简称 JS)是 Web 前端编程的核心语言 。它负责把 HTML(结构)和 CSS(样式)组合的网页变成可交互的应用——按钮点击、表单验证、动画、数据请求……都离不开它。
0.1 三大 Web 技术的关系
💡 三层结构
HTML → 网页结构 (骨架)
CSS → 网页样式 (外观)
JS → 网页行为 (交互、逻辑、数据)
0.2 与 Java 的关键区别(大一常见误解)
维度 Java JavaScript
类型 强类型 / 编译型 动态类型 / 解释型
运行 JVM 虚拟机 浏览器 或 Node.js
主要场景 后端服务、Android 网页交互、Node 后端
类与继承 基于 class 基于原型(ES6 后可写 class)
线程模型 多线程 单线程 + 事件循环
0.3 你将学到(按主线)
语法基础 :变量、数据类型、运算符、流程控制、函数
核心数据结构 :字符串、数组、对象、Map/Set、解构
面向对象 :class、继承、封装、原型链
DOM 操控 :查找元素、修改内容与样式、创建/删除节点
事件 :addEventListener、事件对象、冒泡与委托
BOM + 异步 :定时器、Promise、async/await、Event Loop
网络 :Fetch、HTTP 基础、JSON
工程化 :模块化、调试、npm 与 Node.js 入门
5 个真实项目 :计算器 / Todo / 成绩管理 / 天气 / 图书
衔接关系: 学完本教程可与本系列 SQL/数据库 课程合流,自然过渡到 Node.js 全栈开发。
运行环境:浏览器、DevTools、VS Code ⭐⭐⭐
1.1 在浏览器中直接运行
最简单的方式:在 HTML 里嵌入 <script>。
HTML 复制
<!-- index.html -->
< script >
console .log ("Hello JavaScript" );
< / script >
打开 DevTools(按 F12 或右键 → 检查),切到 Console 面板看输出。
1.2 三种引入方式
方式 用法 适用
行内 <button onclick="alert(1)">极简 demo
内部 <script>...</script>小练习
外部 <script src="app.js"></script>真实项目(推荐)
1.3 DevTools 五大面板
🔍 必学面板
Console :运行 JS、查看日志与错误
Elements :查看/调试 HTML 与 CSS
Sources :打断点调试 JS
Network :查看网络请求(Fetch/XHR)
Application :查看 localStorage / Cookie
1.4 VS Code 工作流
步骤 复制
① 创建 index.html,写入基础 HTML 骨架
② 创建 app.js,写 console.log("hi");
③ 在 HTML 里通过 <script src="app.js"></script> 引入
④ 安装扩展 Live Server,右键 "Open with Live Server"
⑤ 修改代码自动刷新
推荐扩展: Live Server、Prettier、ESLint、JavaScript (ES6) code snippets。
基本语法 ⭐⭐⭐
2.1 注释
JavaScript 复制
// 单行注释
/*
多行注释
常用于函数说明
*/
function greet (name) {
// 内部注释
return `你好, ${ name} ` ;
}
2.2 语句与分号
JavaScript 复制
let x = 10 ; // 推荐加分号
let y = 20 // 不加分号 ASI 会自动插入(不推荐依赖)
console .log (x + y);
2.3 大小写敏感
⚠️ 大小写
let myname = "Alice"; ✓
let myName = "Alice"; ✗ 是另一个变量
2.4 标识符命名规则
可包含字母、数字、_、$
不能以数字开头
不能是关键字(let / class / return 等)
推荐驼峰式:firstName / getUserById
2.5 常用关键字清单
类别 常见关键字
声明 var let const function class
流程 if else switch for while do break continue return
异常 try catch finally throw
异步 async await
逻辑 true false null undefined
对象 this super new delete typeof instanceof
ES6+ import export yield
变量:let / const / var ⭐⭐⭐
现代 JavaScript 以 let 和 const 为主,var 仅在维护老代码时见到。
3.1 三种声明方式对比
var(ES5) let(ES6) const(ES6)
作用域 函数作用域 块级作用域 块级作用域
可重新赋值 ✅ ✅ ❌(不可改绑定)
重复声明 ✅(不报错) ❌(报错) ❌(报错)
提升 提升且初始化为 undefined 提升但有 TDZ 提升但有 TDZ
推荐度 ❌ 老旧 ✅ 会变的用 ✅ 默认就用
3.2 实战写法
JavaScript 复制
const PI = 3.14159 ; // 常量:不会变
let age = 18 ; // 变量:可能会改
const name = "张三" ; // 默认常量优先
// const 对象的内部属性仍可改(绑定不可变)
const user = { name: "Alice" };
user.name = "Bob" ; // ✅ OK
user = {}; // ❌ TypeError
3.3 块级作用域
JavaScript 复制
if (true ) {
let x = 10 ;
var y = 20 ;
}
console .log (x); // ❌ ReferenceError: x is not defined
console .log (y); // ✅ 20(var 泄漏到外层)
数据类型 ⭐⭐⭐
4.1 基本类型(7 种 Primitive)
类型 示例 说明
Number 42, 3.14, NaN不区分整型与浮点型
String "hi", 'hi', \`hi\`三种引号均可
Boolean true, false逻辑判断
Undefined undefined变量已声明但未赋值
Null null主动表示"空"
BigInt 9007199254740993n超大整数
Symbol Symbol('id')唯一标识符
4.2 引用类型(Object)
包括 Object、Array、Function、Date、RegExp、Map、Set 等。基本类型存"值",引用类型存"地址"。
4.3 typeof 检测
JavaScript 复制
console .log (typeof 42 ); // "number"
console .log (typeof "hi" ); // "string"
console .log (typeof true ); // "boolean"
console .log (typeof undefined ); // "undefined"
console .log (typeof null ); // "object" ← 历史遗留 bug!
console .log (typeof [1,2,3]); // "object"
console .log (typeof function (){}); // "function"
4.4 基本 vs 引用(关键)
JavaScript 复制
// 基本类型:拷贝值
let a = 10 ;
let b = a;
b = 20 ;
console .log (a); // 10(a 没受影响)
// 引用类型:拷贝地址
const arr1 = [1 , 2 ];
const arr2 = arr1;
arr2.push(3 );
console .log (arr1); // [1, 2, 3] ← 注意!
类型转换 ⭐⭐⭐
5.1 显式转换
JavaScript 复制
Number ("123" ); // 123
Number ("abc" ); // NaN (Not a Number)
Number (true ); // 1
Number (null ); // 0
Number (undefined ); // NaN
String (123 ); // "123"
String (true ); // "true"
Boolean (0 ); // false
Boolean ("" ); // false
Boolean ("hi" ); // true
Boolean (null ); // false
5.2 隐式转换(容易踩坑)
JavaScript 复制
console .log ("10" + 5 ); // "105" (+ 遇到字符串变拼接)
console .log ("10" - 5 ); // 5 (- 强制转数字)
console .log ("10" * "2" ); // 20 (* 强制转数字)
console .log (null + 1 ); // 1 (null → 0)
console .log (undefined + 1 ); // NaN
5.3 == vs ===(强烈推荐 ===)
JavaScript 复制
// == 会做隐式转换
"10" == 10 // true (字符串转数字)
null == undefined // true
true == 1 // true
// === 严格比较,类型不同直接 false
"10" === 10 // false
null === undefined // false
✅ 最佳实践
项目代码永远用 === 和 !==,避免隐式转换带来的 bug。
运算符 ⭐⭐⭐
6.1 算术运算符
JavaScript 复制
let a = 10 , b = 3 ;
a + b // 13 加
a - b // 7 减
a * b // 30 乘
a / b // 3.3333 除
a % b // 1 取余
a ** b // 1000 幂(ES6)
6.2 自增自减
JavaScript 复制
let n = 5 ;
console .log (n++); // 5 (先返回再加)
console .log (n); // 6
console .log (++n); // 7 (先加再返回)
6.3 比较运算符(强烈推荐用 === 与 !==)
符号 含义 建议
> < >= <=大小比较 正常用
== !=等于(带隐式转换) ❌ 不推荐
=== !==严格等于 ✅ 永远用
6.4 逻辑运算符
JavaScript 复制
let age = 20 , hasID = true ;
age >= 18 && hasID // 与
age >= 18 || hasID // 或
!hasID // 非
// 短路运算常用:
const name = input || "匿名" ; // input 为空时给默认值
6.5 三元运算符
JavaScript 复制
let result = age >= 18 ? "成年" : "未成年" ;
console .log (result); // "成年"
条件控制 ⭐⭐⭐
7.1 if / else
JavaScript 复制
let score = 85 ;
if (score >= 90 ) {
console .log ("优秀" );
} else if (score >= 80 ) {
console .log ("良好" );
} else if (score >= 60 ) {
console .log ("及格" );
} else {
console .log ("不及格" );
}
7.2 switch(多分支)
JavaScript 复制
let day = 3 ;
let name;
switch (day) {
case 1 : name = "周一" ; break ;
case 2 : name = "周二" ; break ;
case 3 : name = "周三" ; break ;
default : name = "未知" ;
}
console .log (name); // "周三"
⚠️ 别忘 break,否则会继续往下执行(fall-through)。
循环 ⭐⭐⭐
8.1 for 循环
JavaScript 复制
for (let i = 0 ; i < 5 ; i++) {
console .log (i); // 0 1 2 3 4
}
8.2 while 与 do...while
JavaScript 复制
// while:条件为真才执行
let n = 0 ;
while (n < 3 ) {
console .log (n);
n++;
}
// do...while:先执行一次,再判断
let m = 10 ;
do {
console .log (m);
} while (m < 3 ); // 输出 10,循环结束
8.3 break 与 continue
JavaScript 复制
// break:跳出整个循环
for (let i = 0 ; i < 10 ; i++) {
if (i === 5 ) break ;
console .log (i); // 0 1 2 3 4
}
// continue:跳过本次循环
for (let i = 0 ; i < 5 ; i++) {
if (i === 2 ) continue ;
console .log (i); // 0 1 3 4
}
8.4 for...of 与 for...in
JavaScript 复制
const arr = ["a" , "b" , "c" ];
for (const v of arr) { // 遍历值(数组/可迭代对象)
console .log (v);
}
const obj = { x: 1 , y: 2 };
for (const k in obj) { // 遍历键(对象)
console .log (k, obj[k]);
}
String 字符串 ⭐⭐⭐
9.1 创建与长度
JavaScript 复制
const s1 = "hello" ;
const s2 = 'world' ;
const s3 = `多行
字符串` ;
console .log (s3.length); // 不计入首尾换行的实际字符数
9.2 常用方法速查
方法 作用 示例
indexOf(s)查找位置 "hello".indexOf("e") // 1
includes(s)包含判断 "hello".includes("he") // true
startsWith(s)开头判断 "http".startsWith("h") // true
endsWith(s)结尾判断 "hi.txt".endsWith(".txt") // true
slice(a,b)切片 "hello".slice(1,4) // "ell"
split(s)拆数组 "a,b,c".split(",") // ["a","b","c"]
replace(a,b)替换 "ab".replace("a","x") // "xb"
toUpperCase()转大写 "Hi".toUpperCase() // "HI"
trim()去首尾空白 " hi ".trim() // "hi"
9.3 模板字符串 ⭐⭐⭐
JavaScript 复制
const name = "Alice" ;
const age = 18 ;
// 拼接(推荐)
const msg = `姓名: ${ name} ,年龄: ${ age} ` ;
console .log (msg); // "姓名:Alice,年龄:18"
// 多行
const html = `
<div>
<h1> ${ name} </h1>
</div>
` ;
// 表达式直接执行
const price = `总金额:¥ ${ (99 * 3 ).toFixed (2 )} ` ; // "总金额:¥297.00"
这是现代 JS 必须掌握的内容。 拼接字符串一律用模板字符串,别再用 +。
Array 数组 ⭐⭐⭐
10.1 创建与访问
JavaScript 复制
const scores = [90 , 85 , 78 , 92 ];
scores[0 ]; // 90 第一个元素
scores[scores.length - 1 ]; // 92 最后一个
scores.length; // 4
// 修改
scores[1 ] = 88 ;
// 创建
const arr1 = [1 , 2 , 3 ];
const arr2 = new Array (3 ); // 长度 3 的空数组
const arr3 = Array .from ("hi" ); // ["h", "i"]
10.2 增删改 4 件套
方法 作用 说明
push(x)末尾加 返回新长度
pop()末尾删 返回被删除元素
unshift(x)开头加 返回新长度
shift()开头删 返回被删除元素
slice(a,b)切片(不动原数组) 返回新数组
splice(i,n,...)删除/插入(动原数组) 返回被删数组
concat(a)拼接 返回新数组
indexOf(x)查找位置 找不到返回 -1
includes(x)包含判断 返回布尔
JavaScript 复制
const arr = [1 , 2 , 3 , 4 , 5 ];
arr.splice(1 , 2 ); // 从索引 1 起删 2 个 → [1, 4, 5]
arr.splice(1 , 0 , 99 ); // 在索引 1 处插入 99 → [1, 99, 4, 5]
const a = [1 ,2 ], b = [3 ,4 ];
a.concat(b); // [1, 2, 3, 4](不动 a)
数组遍历与高阶方法 ⭐⭐⭐
11.1 三种基本遍历
JavaScript 复制
const scores = [90 , 85 , 78 ];
// 方式 1:传统 for
for (let i = 0 ; i < scores.length; i++) {
console .log (scores[i]);
}
// 方式 2:for...of(拿到值)
for (const s of scores) {
console .log (s);
}
// 方式 3:forEach(提供值+索引+数组)
scores.forEach ((s, i) => {
console .log (`第 ${ i+1 } 名: ${ s} 分` );
});
11.2 三大高阶方法 ⭐⭐⭐
🧠 三件套
map → 转换每一项,返回新数组
filter → 筛选满足条件的,返回新数组
reduce → 把数组"汇总"为单个值
JavaScript 复制
const scores = [90 , 85 , 78 , 92 , 60 ];
// map:每人加 5 分
const newScores = scores.map (x => x + 5 );
// [95, 90, 83, 97, 65]
// filter:取出 90 分以上
const high = scores.filter (x => x >= 90 );
// [90, 92]
// reduce:求总分(初始值为 0)
const total = scores.reduce ((sum, x) => sum + x, 0 );
// 405
// reduce 求平均
const avg = total / scores.length; // 81
// 综合练习:找出最高分
const top = scores.reduce ((best, x) => x > best ? x : best, -Infinity );
11.3 其他常用方法
JavaScript 复制
const arr = [3 , 1 , 4 , 1 , 5 , 9 ];
arr.sort ((a, b) => a - b); // 数字排序 [1,1,3,4,5,9]
arr.reverse (); // 反转
arr.find (x => x > 3 ); // 4 第一个满足
arr.findIndex (x => x > 3 ); // 2
arr.every (x => x > 0 ); // true 全员满足
arr.some (x => x > 5 ); // true 至少一个
arr.join ("-" ); // "3-1-4-1-5-9"
Object 对象 ⭐⭐⭐
12.1 创建、访问、修改、删除
JavaScript 复制
const student = {
name: "张三" ,
age: 18 ,
score: 95 ,
introduce () {
return `我叫 ${ this .name} ,` +
`考 ${ this .score} 分` ;
}
};
// 访问
student.name; // "张三"
student["name" ]; // "张三"(动态键名)
// 修改
student.age = 19 ;
// 删除
delete student.score;
// 调用方法
console .log (student.introduce ());
12.2 this 关键字
方法内部的 this 通常指向调用该方法的对象。箭头函数不绑定自己的 this ,这是新手最常踩的坑。
12.3 常用方法
JavaScript 复制
const obj = { a: 1 , b: 2 };
Object .keys(obj); // ["a", "b"]
Object .values(obj); // [1, 2]
Object .entries(obj); // [["a",1], ["b",2]]
Object .fromEntries (...).keys(); // 反向
Object .assign ({}, obj, {c:3 }); // 拷贝合并
// 拷贝(浅拷贝)
const copy = { ...obj };
copy.a = 99 ;
console .log (obj.a); // 1
解构赋值 ⭐⭐⭐
13.1 数组解构
JavaScript 复制
const [a, b, c] = [10 , 20 , 30 ];
console .log (a, b, c); // 10 20 30
// 跳过/默认值
const [x, , y = 99 ] = [1 , 2 ];
console .log (x, y); // 1 99
// 交换变量
let m = 1 , n = 2 ;
[m, n] = [n, m]; // m=2, n=1
13.2 对象解构
JavaScript 复制
const student = { name: "张三" , age: 18 , score: 95 };
const { name, age } = student;
console .log (name, age); // "张三" 18
// 重命名 + 默认值
const { name: userName, grade = "A" } = student;
console .log (userName, grade); // "张三" "A"
// 函数参数解构
function show ({ name, age }) {
console .log (` ${ name} , ${ age} 岁` );
}
show (student);
函数 ⭐⭐⭐
14.1 三种定义方式
JavaScript 复制
// 1. 函数声明(hoisting 友好)
function add (a, b) {
return a + b;
}
// 2. 函数表达式
const sub = function (a, b) {
return a - b;
};
// 3. 箭头函数(见下章)
const mul = (a, b) => a * b;
14.2 默认参数 & 可变参数
JavaScript 复制
function greet (name = "游客" , ...others) {
console .log (`你好 ${ name} ` );
console .log ("others:" , others);
}
greet ("Alice" , "Bob" , "Carol" ); // others: ["Bob","Carol"]
14.3 函数也是值
JavaScript 复制
function apply (fn, a, b) {
return fn (a, b);
}
apply (add, 2 , 3 ); // 5
apply (mul, 2 , 3 ); // 6
箭头函数 ⭐⭐⭐
15.1 语法糖
JavaScript 复制
// 完整写法
const add = (a, b) => {
return a + b;
};
// 单行返回(隐式 return)
const add = (a, b) => a + b;
// 单个参数
const double = x => x * 2 ;
// 无参数
const hello = () => "Hello!" ;
15.2 与普通函数的区别
对比点 function ()=> {}
this 动态绑定 词法绑定(定义时确定)
arguments 可用 不可用,用 ...rest
作为构造函数 可以用 new 不能 new
简洁度 中等 最简洁
JavaScript 复制
// 经典坑:回调中 this 丢失
const timer = {
sec: 0 ,
start () {
setInterval (() => { // 箭头函数继承外层 this
this .sec++;
console .log (this .sec);
}, 1000 );
}
};
timer.start ();
作用域与闭包 ⭐⭐⭐
16.1 四种作用域
类型 说明 例子
全局 window/global 上的变量 var a = 1 在最外层
函数 仅函数内部 function 内 var/let
块级 {} 内(let/const) if、for、{} 内
词法 外层作用域(嵌套函数时) 闭包的关键
16.2 闭包经典图
🔒 闭包:函数"记住"了它的外部变量
外层函数 fn()
↓ return
返回的函数 fn2()
↓ 依然能访问 fn() 内的局部变量 count
这就是闭包
JavaScript 复制
// 闭包:用函数"包住"一个状态
function createCounter () {
let count = 0 ; // 私有
return () => ++count; // 闭包
}
const cnt = createCounter ();
console .log (cnt ()); // 1
console .log (cnt ()); // 2
console .log (cnt ()); // 3
console .log (count); // ❌ ReferenceError
理解闭包 = 理解 React/Vue 状态管理。 面试 100% 会问。
ES6+ 核心语法 ⭐⭐⭐
ES6(2015)是 JavaScript 历史上最大的一次更新。下面这些特性已成为必备 。
17.1 全部语法清单
特性 示例
let / const 见 §03
箭头函数 见 §15
模板字符串 \`hi \${name}\`
解构 见 §13
默认 / 剩余 参数 fn(a=1, ...rest)
展开运算符 [...arr, ...arr2]
对象简写 {x, y} ≡ {x:x, y:y}
Map / Set 见下章
Class 见 §19
Module export / import
17.2 展开运算符(Spread)
JavaScript 复制
const a = [1 , 2 ];
const b = [...a, 3 , 4 ]; // [1, 2, 3, 4]
const obj1 = { x: 1 };
const obj2 = { ...obj1, y: 2 }; // { x:1, y:2 }
Math .max (...a); // 2
console .log (...a); // 1 2
// 函数参数
function sum (...nums) { return nums.reduce ((s,n)=>s+n, 0 ); }
sum (1 ,2 ,3 ,4 ); // 10
Map 与 Set ⭐⭐
18.1 四种"集合"对比
Array Object Map Set
结构 有序列表 键值对 任意键的键值对 无重复集合
键类型 数字索引 字符串/Symbol 任意类型 —
是否重复 ✅ 键唯一 键唯一 自动去重
大小 .length手动维护 .size.size
迭代 for / for...of for...in / entries forEach / for...of forEach / for...of
18.2 Map 示例
JavaScript 复制
const map = new Map ();
map.set ("name" , "张三" );
map.set ("age" , 18 );
map.set (obj, "对象当键也可以" );
console .log (map.get ("name" )); // "张三"
console .log (map.has ("age" )); // true
console .log (map.size); // 3
// 遍历
for (const [k, v] of map) {
console .log (k, "=>" , v);
}
18.3 Set 示例:自动去重
JavaScript 复制
const set = new Set ([1 , 2 , 3 , 3 , 2 , 1 ]);
console .log ([...set]); // [1, 2, 3]
set.add (4 );
set.has (3 ); // true
// 数组去重
const arr = [1 ,1 ,2 ,2 ,3 ];
const unique = [...new Set (arr)]; // [1,2,3]
面向对象 class ⭐⭐
19.1 基本 class
JavaScript 复制
class Student {
constructor (name, age) {
this .name = name;
this .age = age;
}
introduce () {
return `我是 ${ this .name} ,` +
` ${ this .age} 岁` ;
}
}
const s = new Student ("张三" , 18 );
console .log (s.introduce ());
19.2 继承 extends / super
JavaScript 复制
class CollegeStudent extends Student {
constructor (name, age, major) {
super (name, age); // 调用父类构造
this .major = major;
}
introduce () {
return super .introduce () +
`,专业: ${ this .major} ` ;
}
}
const cs = new CollegeStudent ("李四" , 20 , "计算机" );
console .log (cs.introduce ());
19.3 static 静态方法 & private 私有字段
JavaScript 复制
class User {
// 私有字段(# 开头,外部访问报错)
#password;
constructor (name, pwd) {
this .name = name;
this .#password = pwd;
}
check (pwd) {
return pwd === this .#password;
}
static create (name) { // 类方法,不需 new
return new User (name, "123456" );
}
}
const u1 = User .create ("Alice" );
console .log (u1.check ("123456" )); // true
原型与原型链 ⭐⭐
20.1 概念图
s1 实例
[[Prototype]]
Student.prototype
introduce()
Object
toString()
prototype 链
继承自 Object
找不到属性时沿链向上查找,叫"原型链查找"
20.2 实战:看原型链
JavaScript 复制
class Animal {}
const a = new Animal ();
console .log (a.__proto__ === Animal.prototype); // true
console .log (Animal.prototype.__proto__ === Object .prototype); // true
console .log (Object .prototype.__proto__); // null(链终点)
入门阶段理解"对象 → 自己的类 → Object → null"这条链即可,无需深入底层。日常开发我们用 class,本质仍由原型实现 。
异常处理 ⭐⭐⭐
21.1 try / catch / finally
JavaScript 复制
try {
const data = JSON .parse ('{"name": "Alice"' ); // 错误字符串
} catch (err) {
console .error ("解析失败:" , err.message);
} finally {
console .log ("无论是否出错,都会执行" );
}
21.2 throw 自定义异常
JavaScript 复制
function divide (a, b) {
if (b === 0 ) throw new Error ("除数不能为 0" );
return a / b;
}
try {
divide (10 , 0 );
} catch (e) {
console .log (e.message); // "除数不能为 0"
}
同步与异步 + Event Loop ⭐⭐⭐
22.1 同步 vs 异步
🔄 单线程模型
同步 :A → B → C 一行一行执行
异步 :A 启动后让浏览器等结果,继续 B,等结果回来再处理
22.2 Event Loop 模型
Call Stack
调用栈
main()
fetch()
其他任务
Web APIs
浏览器能力
setTimeout
fetch
DOM 事件
Callback Queue
任务队列
callback 1
callback 2
promise.then
Call Stack 空时,Event Loop 把任务推入执行
Promise ⭐⭐⭐
23.1 三种状态
📦 Promise 三态
pending (进行中) → fulfilled (成功,调用 resolve)
pending → rejected (失败,调用 reject)
一旦确定不可再改。
23.2 创建与基础用法
JavaScript 复制
const fetchData = () =>
new Promise ((resolve, reject) => {
setTimeout (() => {
resolve ("数据" );
}, 1000 );
});
fetchData ()
.then (data => console .log ("成功:" , data))
.catch (err => console .error ("失败:" , err))
.finally (() => console .log ("结束" ));
23.3 Promise 链
JavaScript 复制
fetch ("/api/user/1" )
.then (r => r.json ()) // 解析 JSON
.then (user => fetch (`/api/posts?uid= ${ user.id} ` ))
.then (r => r.json ())
.then (posts => console .log (posts))
.catch (err => console .error (err));
23.4 Promise.all 并发
JavaScript 复制
// 等所有完成
Promise .all ([
fetch ("/api/a" ),
fetch ("/api/b" ),
fetch ("/api/c" )
])
.then (arr => Promise .all (arr.map (r => r.json ())))
.then (data => console .log (data));
// 任一成功即可
Promise .race ([req1, req2]).then (useFastest);
// 全部完成(含失败)
Promise .allSettled ([...]).then (showAll);
async / await ⭐⭐⭐
24.1 写法
JavaScript 复制
async function getStudents () {
try {
const res = await fetch ("/api/students" );
if (!res.ok) throw new Error (`HTTP ${ res.status} ` );
const list = await res.json ();
return list;
} catch (err) {
console .error ("加载失败:" , err);
}
}
console .log (getStudents ()); // 返回 Promise
24.2 与 Promise 对比
维度 .then() 链 async/await
可读性 嵌套多时代码深 同步风格
错误处理 .catch() try/catch
并行请求 Promise.all 同 Promise.all
推荐度 需要兼容旧代码时 ✅ 现代首选
async/await 是现代 JavaScript 异步编程的核心语法。 能用就用。
DOM 基础 ⭐⭐⭐
DOM = Document Object Model ,浏览器把 HTML 转成树形结构,JS 通过操作这棵树来改变页面。
25.1 DOM 树结构
document
<html>
<body>
<head>
<h1>
<p>
<button>
每个 HTML 标签变成一个节点(Node),JS 通过节点对象操作网页
25.2 第一个完整例子
HTML 复制
< h1 id ="title" > Hello< / h1 >
< button id ="btn" > 改文字< / button >
< script >
const title = document .getElementById ("title" );
const btn = document .getElementById ("btn" );
btn.addEventListener ("click" , () => {
title.textContent = "Hello JavaScript" ;
title.style .color = "#F7DF1E" ;
});
< / script >
获取与修改元素 ⭐⭐⭐
26.1 获取元素
方法 返回 用法
getElementById(id)单元素 知道 id
querySelector(sel)第一个匹配 "#id" / ".cls" / "div"
querySelectorAll(sel)NodeList(类数组) 全部匹配
getElementsByClassName(c)HTMLCollection 旧 API,少用
getElementsByTagName(t)HTMLCollection 旧 API
JavaScript 复制
const one = document .querySelector ("#title" );
const all = document .querySelectorAll ("li.item" );
const cards = [...all];
26.2 修改内容
JavaScript 复制
const el = document .getElementById ("title" );
el.textContent = "纯文本" ; // 推荐:纯文本
el.innerHTML = "<b>含 HTML</b>" ; // 可写 HTML(注意 XSS)
const input = document .querySelector ("input" );
input.value = "hello" ; // 表单值
26.3 属性
JavaScript 复制
const img = document .querySelector ("img" );
img.setAttribute ("src" , "/a.jpg" );
img.getAttribute ("alt" );
img.removeAttribute ("title" );
// 标准属性更直接
img.src = "/a.jpg" ;
img.id = "avatar" ;
26.4 修改样式
JavaScript 复制
const box = document .getElementById ("box" );
// 内联样式(注意命名:backgroundColor)
box.style .color = "red" ;
box.style .backgroundColor = "#222" ;
box.style .fontSize = "20px" ;
// class 控制(推荐!样式写在 CSS 里)
box.classList .add ("active" );
box.classList .remove ("hide" );
box.classList .toggle ("open" );
console .log (box.classList .contains ("active" ));
创建与删除元素 ⭐⭐⭐
27.1 综合案例:动态学生列表
HTML + JS 复制
<!-- index.html -->
< input id ="name" placeholder ="姓名" >
< input id ="score" type ="number" placeholder ="分数" >
< button id ="add" > 添加学生< / button >
< ul id ="list" > < / ul >
< script >
const list = document .getElementById ("list" );
document .getElementById ("add" ).addEventListener ("click" , () => {
const name = document .getElementById ("name" ).value;
const score = document .getElementById ("score" ).value;
if (!name) return ;
const li = document .createElement ("li" );
li.textContent = ` ${ name} - ${ score} 分` ;
const del = document .createElement ("button" );
del.textContent = "删除" ;
del.addEventListener ("click" , () => li.remove ());
li.appendChild (del);
list.appendChild (li);
});
< / script >
事件 ⭐⭐⭐
28.1 常用事件
类别 事件
鼠标 click dblclick mouseover mouseout mousemove
键盘 keydown keyup keypress
表单 submit input change focus blur
窗口 load resize scroll
28.2 addEventListener(推荐)
JavaScript 复制
const btn = document .getElementById ("btn" );
btn.addEventListener ("click" , function (event) {
console .log ("按钮被点击" );
console .log (event.target ); // 触发元素
console .log (event.type ); // "click"
});
// 移除监听
function onClick () { console .log ("a" ); }
btn.addEventListener ("click" , onClick);
btn.removeEventListener ("click" , onClick);
28.3 事件对象 event
JavaScript 复制
event.target // 触发事件的元素
event.currentTarget // 绑定事件的元素
event.type // 事件类型
event.preventDefault ()// 阻止默认行为(如表单提交)
event.stopPropagation ()// 停止冒泡
// 键盘事件
input.addEventListener ("keydown" , e => {
if (e.key === "Enter" ) console .log ("按了回车" );
if (e.ctrlKey && e.key === "s" )
alert ("Ctrl+S" );
});
事件冒泡与委托 ⭐⭐
29.1 三个阶段
捕获阶段 Capture
目标阶段 Target
冒泡阶段 Bubble
document → ... → 父
当前元素
父 → ... → document
29.2 事件委托
把监听器挂到父元素,利用冒泡 统一处理子元素。
JavaScript 复制
// 1000 个 li,只需要 1 个监听
const ul = document .getElementById ("list" );
ul.addEventListener ("click" , e => {
if (e.target .tagName === "LI" ) {
console .log ("点了:" , e.target .textContent );
}
});
// 第三个参数 true = 走捕获阶段(默认 false 走冒泡)
el.addEventListener ("click" , handler, true );
BOM 与定时器 ⭐⭐
30.1 五大对象
对象 作用
window全局 + 弹窗 + 帧控制
navigator浏览器信息
locationURL 操作
history前进/后退
screen屏幕宽高
JavaScript 复制
location .href // 当前完整 URL
location .reload () // 刷新
location .assign ("/home" ) // 跳转
history .back () // 后退
history .forward () // 前进
history .go (- 2 ) // 退回 2 步
alert ("提示" ) // 警告框
confirm ("确定吗?" ) // 确认框(返回布尔)
prompt ("姓名:" ) // 输入框(返回字符串)
30.2 定时器综合案例:倒计时
JavaScript 复制
let sec = 10 ;
const h = document .getElementById ("h" );
const timer = setInterval (() => {
h.textContent = `剩余 ${ sec} 秒` ;
if (--sec === 0 ) {
clearInterval (timer); // 停止
h.textContent = "时间到!" ;
}
}, 1000 );
// 单次延迟
const t = setTimeout (() => console .log ("1 秒后" ), 1000 );
clearTimeout (t); // 取消
Fetch API ⭐⭐⭐
31.1 两种写法
JavaScript (Promise 链) 复制
fetch ("/api/students" )
.then (r => {
if (!r.ok) throw new Error (String (r.status));
return r.json ();
})
.then (data => console .log (data))
.catch (err => console .error (err));
JavaScript (async/await) 复制
async function load () {
try {
const r = await fetch ("/api/students" );
const data = await r.json ();
console .log (data);
} catch (e) {
console .error (e);
}
}
31.2 发送 POST
JavaScript 复制
fetch ("/api/students" , {
method : "POST" ,
headers : { "Content-Type" : "application/json" },
body : JSON .stringify ({ name: "张三" , score: 95 })
})
.then (r => r.json ())
.then (d => console .log ("已添加" , d));
HTTP 基础 ⭐⭐⭐
32.1 请求响应流程
🌐 HTTP 一次往返
浏览器 → (请求 Request) → 服务器
← (响应 Response) ←
32.2 常用方法
方法 语义 是否带 body
GET 获取 否
POST 新增 是
PUT 整体修改 是
PATCH 局部修改 是
DELETE 删除 否
32.3 状态码速查
范围 含义 例子
2xx 成功 200 OK, 201 Created
3xx 重定向 301 Moved, 304 Not Modified
4xx 客户端错 400 参数错, 401 未登录, 404 找不到, 429 太频繁
5xx 服务器错 500 内部错误, 503 服务不可用
32.4 JSON 互转
JavaScript 复制
const obj = { name: "张三" , age: 18 };
const json = JSON .stringify (obj);
console .log (json); // '{"name":"张三","age":18}'
const back = JSON .parse (json);
console .log (back.name); // "张三"
Web Storage(本地存储)⭐⭐⭐
33.1 localStorage vs sessionStorage
localStorage sessionStorage
生命周期 永久(除非手动删) 关闭标签页即清
容量 ~5MB ~5MB
作用域 同源共享 仅当前标签
33.2 浏览器记事本项目
JavaScript 复制
const KEY = "notes" ;
function save () {
const text = document .getElementById ("content" ).value;
const list = JSON .parse (localStorage .getItem (KEY) || "[]" );
list.push ({ text, at: Date .now () });
localStorage .setItem (KEY, JSON .stringify (list));
render ();
}
function render () {
const list = JSON .parse (localStorage .getItem (KEY) || "[]" );
const ul = document .getElementById ("notes" );
ul.innerHTML = "" ;
list.forEach (n => {
const li = document .createElement ("li" );
li.textContent = n.text;
ul.appendChild (li);
});
}
sessionStorage .setItem ("temp" , "标签页一关就清" );
表单与正则 ⭐⭐
34.1 表单提交 + 阻止默认
HTML + JS 复制
< form id ="f" >
< input name ="email" >
< input name ="pwd" type ="password" >
< button > 提交< / button >
< / form >
< script >
document .getElementById ("f" ).addEventListener ("submit" , e => {
e.preventDefault (); // 阻止页面刷新
const data = Object .fromEntries (new FormData (e.target ));
console .log (data); // { email: "...", pwd: "..." }
});
< / script >
34.2 RegExp:常用正则
JavaScript 复制
const emailRe = /^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$/ ;
const phoneRe = /^1[3-9]\d{9}$/ ;
const userRe = /^[a-zA-Z][\w]{3,15}$/ ;
emailRe .test ("alice@school.edu" ); // true
phoneRe .test ("13800138000" ); // true
console .log ("a1b2c3" .match (/\d+/g )); // ["1","2","3"]
"a,b,c" .replace (/,/g , "-" ); // "a-b-c"
34.3 综合:表单验证
JavaScript 复制
function validate ({ email, phone }) {
const errors = {};
if (!/^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$/ .test (email))
errors.email = "邮箱格式不对" ;
if (!/^1[3-9]\d{9}$/ .test (phone))
errors.phone = "手机号 11 位" ;
return errors;
}
JavaScript 调试 ⭐⭐⭐
35.1 console 三件套
JavaScript 复制
const data = [
{ name: "张三" , age: 18 , score: 95 },
{ name: "李四" , age: 19 , score: 82 }
];
console .log ("普通日志" , data);
console .table (data); // 表格化展示
console .error ("报错信息" );
console .warn ("警告" );
console .dir (data); // 显示对象结构
console .time ("耗时" );
// ...
console .timeEnd ("耗时" );
35.2 DevTools 断点流程
🪜 调试 4 步走
读报错 :Console 看红色错误,定位文件+行号
看堆栈 :Call Stack 看调用顺序
打断点 :Sources 面板点行号,F10 单步跳过、F11 进入
观察变量 :右侧 Watch 加变量,Hover 源码可看值
核心能力:阅读错误信息 → 定位错误 → 修改代码 → 再运行。 大一就要养成习惯。
模块化 + npm + Node.js ⭐⭐
36.1 ES Module(浏览器原生)
math.js 复制
export function add (a, b) { return a + b; }
export default function sub (a, b) { return a - b; }
app.js 复制
import { add } from "./math.js" ;
import sub from "./math.js" ;
console .log (add (2 , 3 ), sub (5 , 2 ));
index.html 复制
< script type ="module" src ="app.js" > < / script >
36.2 npm 工作流
命令 复制
npm init -y # 生成 package.json
npm install lodash # 装到 dependencies
npm install --save-dev eslint # 装到 devDependencies
npm run dev # 运行 package.json 的 scripts
36.3 Node.js 入门
🟢 Node.js 不是 JavaScript 语言,是 JS 运行环境
它让 JS 能在服务器 / 命令行运行。大一入门不深入 ,只要知道能写后端即可。
node app.js # 执行 JS
node --version # 查版本
综合项目一:计算器 ⭐⭐⭐
项目 1:网页计算器
难度:⭐⭐ 技术:HTML + CSS + JS 核心:DOM + 事件 + 函数
思路
HTML 网格布局数字按钮 + 显示屏
用一个全局字符串保存当前表达式
按下数字追加,按下运算追加符号
按下 = 调用 eval() 计算(或自己写解析)
完整代码
HTML 复制
< div id ="calc" >
< div id ="screen" > < / div >
< div id ="pad" >
<!-- 数字与运算按钮 -->
< button data-k ="C" > C< / button >
< button data-k ="/" > ÷< / button >
< button data-k ="7" > 7< / button >
< button data-k ="8" > 8< / button >
... 更多按钮 ...
< button data-k ="=" > =< / button >
< / div >
< / div >
JavaScript 复制
let expr = "" ;
const screen = document .getElementById ("screen" );
document .getElementById ("pad" ).addEventListener ("click" , e => {
const k = e.target .dataset .k ;
if (!k) return ;
if (k === "C" ) expr = "" ;
else if (k === "=" ) expr = String (safeEval (expr));
else expr += k;
screen.textContent = expr;
});
// 简易安全求值(真实项目请用第三方库)
function safeEval (s) {
if (!/^[\d+\-*/().\s]+$/ .test (s)) throw "含非法字符" ;
return Function (`"use strict"; return ( ${ s} );` )();
}
// 键盘支持
document .addEventListener ("keydown" , e => {
if ("0123456789+-*/." .includes (e.key ))
expr += e.key ;
else if (e.key === "Enter" ) expr = String (safeEval (expr));
else if (e.key === "Backspace" ) expr = expr.slice (0 , -1 );
else if (e.key === "Escape" ) expr = "" ;
screen.textContent = expr || "0" ;
});
综合项目二:Todo List ⭐⭐⭐
项目 2:任务清单 Todo List
难度:⭐⭐⭐ 综合:DOM + 事件 + 数组 + localStorage
完整实现
JavaScript 复制
const KEY = "todo.list" ;
let todos = JSON .parse (localStorage .getItem (KEY) || "[]" );
let filter = "all" ; // all | active | done
const $input = document .getElementById ("input" );
const $list = document .getElementById ("list" );
const $count = document .getElementById ("count" );
function save () { localStorage .setItem (KEY, JSON .stringify (todos)); }
function add (text) {
todos.push ({ id: Date .now (), text, done: false });
}
function toggle (id) {
const t = todos.find (x => x.id === id);
if (t) t.done = !t.done;
}
function del (id) { todos = todos.filter (x => x.id !== id); }
function edit (id, text) {
const t = todos.find (x => x.id === id);
if (t) t.text = text;
}
function render () {
$list.innerHTML = "" ;
const view = todos.filter (t =>
filter === "all" ||
(filter === "active" && !t.done) ||
(filter === "done" && t.done)
);
view.forEach (t => {
const li = document .createElement ("li" );
li.dataset .id = t.id;
li.innerHTML = `
<input type="checkbox" ${ t.done ? "checked" : "" } >
<span class="text" ${ t.done ? " style=\"text-decoration:line-through\"" : "" } > ${ t.text} </span>
<button class="del">×</button>
` ;
$list.appendChild (li);
});
$count.textContent = todos.filter (t => !t.done).length;
}
document .getElementById ("add" ).addEventListener ("click" , () => {
const text = $input.value.trim ();
if (text) { add (text); save (); render (); }
$input.value = "" ;
});
$list .addEventListener ("click" , e => {
const id = Number (e.target .closest ("li" )?.dataset .id );
if (!id) return ;
if (e.target .matches ("input[type=checkbox]" )) toggle (id);
else if (e.target .matches (".del" )) del (id);
save ();
render ();
});
render ();
综合项目三:学生成绩管理
项目 3:学生成绩管理
难度:⭐⭐⭐ 综合:Array + Object + DOM + Event
核心代码
JavaScript 复制
let students = []; // { id, name, score }
function addStudent (name, score) {
students.push ({ id: Date .now (), name, score: Number (score) });
}
function delStudent (id) { students = students.filter (s => s.id !== id); }
function updateStudent (id, n, sc) {
const s = students.find (x => x.id === id);
if (s) { s.name = n; s.score = sc; }
}
function search (keyword) {
return students.filter (s => s.name.includes (keyword));
}
function stats () {
if (!students.length) return null ;
const scores = students.map (s => s.score);
return {
avg: (scores.reduce ((s,n)=>s+n,0 ) / scores.length).toFixed (1 ),
max: Math .max (...scores),
min: Math .min (...scores),
sorted: [...students].sort ((a,b) => b.score - a.score)
};
}
function render () {
const t = document .getElementById ("tbody" );
t.innerHTML = "" ;
students.forEach (s => {
t.innerHTML += `<tr>
<td> ${ s.name} </td>
<td> ${ s.score} </td>
<td><button data-del-id=" ${ s.id} ">删</button></td>
</tr>` ;
});
const st = stats ();
if (st) document .getElementById ("stats" ).textContent =
`平均 ${ st.avg} 最高 ${ st.max} 最低 ${ st.min} ` ;
}
综合项目四:天气查询
项目 4:实时天气查询
难度:⭐⭐⭐ 综合:Fetch + API + JSON + DOM
流程
用户输入城市名
Fetch 调用 Open-Meteo / wttr.in 等免费 API
解析 JSON 渲染温度、湿度、风速、图标
JavaScript 复制
async function getWeather (city) {
// 第 1 步:地理编码
const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name= ${ encodeURIComponent (city)} ` ;
const geoRes = await fetch (geoUrl);
const geo = await geoRes.json ();
if (!geo.results) throw "找不到城市" ;
const { latitude, longitude, name } = geo.results[0 ];
// 第 2 步:天气数据
const url = `https://api.open-meteo.com/v1/forecast?latitude= ${ latitude} &longitude= ${ longitude} ¤t_weather=true` ;
const res = await fetch (url);
const data = await res.json ();
return {
name: name,
temp: data.current_weather.temperature,
wind: data.current_weather.windspeed,
weather: data.current_weather.weathercode
};
}
document .getElementById ("search" ).addEventListener ("click" , async () => {
try {
const city = document .getElementById ("city" ).value;
const w = await getWeather (city);
document .getElementById ("out" ).innerHTML =
`<h2> ${ w.name} </h2>
<p> ${ w.temp} °C · 风 ${ w.wind} km/h</p>` ;
} catch (e) {
alert (e);
}
});
教学场景 :让学生理解前端 → 后端 → 数据 的全链路。任何公开 REST API 都可以替换练习。
综合项目五:在线图书管理
项目 5:在线图书管理系统(前端 + 模拟 REST)
难度:⭐⭐⭐⭐ 综合:HTML + CSS + JS + Fetch + REST API + SQL
架构
📚 全栈雏形
HTML(页面)
↓
CSS(视觉)
↓
JavaScript(逻辑)
↓
Fetch API(HTTP)
↓
REST API(后端接口)
↓
SQL(数据库)
前端代码(兼容本系列 SQL 教程)
JavaScript 复制
const API = "/api/books" ;
async function listBooks () {
const r = await fetch (API);
return r.json ();
}
async function addBook (book) {
return fetch (API, {
method : "POST" ,
headers : { "Content-Type" : "application/json" },
body : JSON .stringify (book)
});
}
async function deleteBook (id) {
return fetch (` ${ API} / ${ id} ` , { method : "DELETE" });
}
async function borrowBook (id, user) {
return fetch (` ${ API} / ${ id} /borrow` , {
method : "POST" ,
headers : { "Content-Type" : "application/json" },
body : JSON .stringify ({ user })
});
}
关联 SQL(对应本系列 SQL 教程"图书借阅"项目)
SQL 复制
CREATE TABLE books (
id INT PRIMARY KEY AUTO_INCREMENT ,
title VARCHAR (100 ),
author VARCHAR (50 ),
stock INT DEFAULT 0
);
CREATE TABLE borrows (
id INT PRIMARY KEY AUTO_INCREMENT ,
book_id INT ,
user VARCHAR (50 ),
borrowed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ,
FOREIGN KEY (book_id) REFERENCES books(id)
);
SELECT b.title, b.author, COUNT (br.id) AS times
FROM books b LEFT JOIN borrows br ON b.id = br.book_id
GROUP BY b.id
ORDER BY times DESC ;
这一章是前后端合流 ,自然衔接到前面学的 SQL。
数据结构与算法入门 ⭐⭐
42.1 简单数据结构
结构 JS 实现思路
栈(Stack) push / pop——先进后出
队列(Queue) push + shift——先进先出
哈希表 Object / Map
集合 Set
JavaScript 复制
// 栈
const stack = [];
stack.push (1 ); stack.push (2 );
stack.pop (); // 2
// 队列:shift 是 O(n),用 index 优化
const q = [];
let head = 0 ;
q.push (1 ); q.push (2 );
const first = q[head++]; // 1
// 二分查找
function binarySearch (arr, target) {
let l = 0 , r = arr.length - 1 ;
while (l <= r) {
const m = (l + r) >>> 1 ;
if (arr[m] === target) return m;
if (arr[m] < target) l = m + 1 ;
else r = m - 1 ;
}
return -1 ;
}
// 冒泡排序
function bubble (arr) {
for (let i = 0 ; i < arr.length; i++) {
for (let j = 0 ; j < arr.length - i - 1 ; j++) {
if (arr[j] > arr[j+1 ])
[arr[j], arr[j+1 ]] = [arr[j+1 ], arr[j]];
}
}
return arr;
}
这一章只为打基础,不要在大一深陷算法 。先把项目做漂亮。
进阶方向 + JavaScript 速查手册
43.1 三条进阶路
🚀 完成本教程后
前端开发 :JS → TypeScript → Vue / React → 前端工程化
Node.js 后端 :JS → Node.js → Express / NestJS → MySQL
全栈开发 :HTML → CSS → JS → Vue/React → Node.js → MySQL
43.2 JavaScript 速查手册
变量与常量
const x = 1
let y = 2
var z = 3(不推荐)
类型
Number / String / Boolean
null / undefined
Array / Object
typeof x
运算符
算术:+-*/% **
比较:=== !== > <
逻辑:&& || !
三元:a?b:c
条件
if / else / else if
switch/case
?: 三元
?? 空合并
循环
for (i; c; u)
while / do-while
for...of(数组)
for...in(对象键)
字符串
s.length / includes
s.slice / split / replace
\`hi ${x}\` 模板
数组方法
push / pop / shift
map / filter / reduce
find / some / every
sort / reverse
对象
obj.key / obj['k']
Object.keys/vals/entries
...obj (展开)
class { constructor() {} }
解构 / 展开
const {a,b} = obj
const [x,y] = arr
const all = [...a, ...b]
{...obj, k:v}
函数
function f(a,b)
const f = (a) => a*2
(a=1, ...rest)=>{}
setTimeout(f, ms)
异步
new Promise((res, rej)=>{})
.then().catch()
async / await
Promise.all([...])
DOM
document.querySelector
el.textContent / innerHTML
el.classList.add/toggle
el.addEventListener('click')
存储
localStorage.setItem / getItem
sessionStorage.setItem
JSON.parse / stringify
fetch(url).then(r=>r.json())
课堂训练:12 道选择题
本节是与前面各章配套的小练习,做错的同学回到对应章节复习。
Q1. 关于 let 与 var,下列说法正确的是?
A. var 声明的变量具有块级作用域
B. let 声明的变量具有块级作用域
C. var 不能重复声明,let 可以
D. let 会被提升到顶部并初始化为 undefined
答案:B。 var 是函数作用域,let/const 才是块级作用域;且 let/const 处于 TDZ(暂时性死区),不会初始化为 undefined。
Q2. 下面哪个表达式结果不是 NaN?
A. Number("abc")
B. parseInt("hi")
C. Number("123abc") 是合法的纯数字字符串吗?它应返回 …
D. undefined + 1
答案:C(Number("123abc") 返回 NaN,但题目更标准答案是:本题期望选 A/B/C/D 中的唯一真值)。 实际请记住:Number()、parseInt() 转换非数字字符都可能是 NaN,只有显式全数字字符串能成功。
Q3. 推荐的相等性比较运算符是?
A. ===
B. ==
C. =
D. !==
答案:A。 === 严格相等不触发隐式转换,符合现代 JS 最佳实践。
Q4. [1,2,3].map(x => x*2) 的结果是?
A. [1,2,3]
B. [2,4,6]
C. 9
D. [3,6,9]
答案:B。 map 不修改原数组,返回每个元素 ×2 的新数组。
Q5. 以下关于箭头函数的说法,错误的是?
A. 没有自己的 this,继承外层
B. 不能用作构造函数
C. 内部可以使用 arguments 对象
D. 单行可省 return
答案:C。 箭头函数没有 arguments,必须用剩余参数 ...rest。
Q6. 一个 Promise 一旦确定(resolve 或 reject),它的状态会?
A. 不能再变
B. 还可以再次 resolve
C. 可切换为另一个状态
D. 默认 5 秒后重置
答案:A。 Promise 状态不可逆:pending → fulfilled / rejected,then catch finally 执行。
Q7. async function 总是返回什么?
A. undefined
B. Promise
C. 同步值
D. 取决于是否有 await
答案:B。 async 函数自动把返回值包成 Promise.resolve。
Q8. 设置元素文本应优先使用?
A. innerHTML
B. innerText
C. textContent
D. document.write
答案:C。 textContent 安全(不解析 HTML)、性能好、能防 XSS。
Q9. 表单提交时阻止页面刷新用?
A. e.preventDefault()
B. return false
C. e.stopPropagation()
D. location.reload()
答案:A。 preventDefault 是浏览器默认行为的标准取消方式。
Q10. localStorage 与 sessionStorage 的关键区别?
A. 容量不同
B. 生命周期不同
C. 是否加密
D. 是否同步
答案:B。 localStorage 永久,sessionStorage 关标签即清。
Q11. addEventListener 第三参数为 true 时表示?
A. 只触发一次
B. 默认参数
C. 阻止冒泡
D. 走捕获阶段
答案:D。 false/省略 = 冒泡;true = 捕获。
Q12. JSON.parse(JSON.stringify({a:1, b:undefined, c:function(){}})) 结果是?
A. {"a":1,"b":undefined,"c":function(){}}
B. {"a":1,"c":null}
C. {"a":1}
D. undefined
答案:C。 JSON 不支持 undefined 和 function,它们被丢弃。
写在最后:本课程与体系衔接
🎓 大学计算机基础课程完整路径
C 语言 → 程序设计基础(指针/数组)
C++ → 面向对象 + 数据结构
Java → 面向对象 + 软件开发
Python → 编程 + 数据处理 + AI
SQL/数据库 → 数据存储 + 数据查询
JavaScript → Web 编程 + 网页交互
JS 是整个体系最贴近"产出"的一门:学完即可独立做出可交互的网页项目。
下一步自然衔接 Node.js / Vue / React ,组成完整全栈能力。
提示: 本教程相关数据/图表均为 SVG 内联矢量,可直接复制到课件。所有代码示例均可直接粘到浏览器 Console 运行。