Files
cs-note/hzh/EXAM/Week06.md
T
2026-05-24 11:42:38 +08:00

22 KiB
Raw Blame History

tags, create time
tags create time
2026-04-30 15:30

前端摸底测试(第六次)— 错题精讲

概述

本次测试涵盖 Axios、AJAX/XHR、JavaScript 核心、DOM/BOM、事件系统、CSS、浏览器存储与定时器、Node.js、Vue 3、React Hooks、Webpack、ESM 模块系统等前端核心技术点。共 110 道单选题,本篇聚焦 37 道错题,按知识点分类逐一拆解错误原因并给出正确理解。

[!tip] 使用建议 先通读各专题的"为什么错 → 为什么对"分析,再做右侧表格的自测检查,最后用「高频考点速览」串记薄弱概念。


一、请求层:Axios & AJAX / XHR

Q03:跨域方案辨析

项目 内容
❌ 你的答案 B(服务器 cors)
✅ 正确答案 D(axios)

Q04:XHR 终止方法

[!note] 纠正说明 此题你答对了。xhr.abort() 是唯一标准方法来中止一个正在进行的 XHR 请求。

Q18:readyState = 3 的含义

项目 内容
❌ 你的答案 C(已应答)
✅ 正确答案 B(交互中)
// XHR readyState 五阶段
const STATE = {
  UNSENT:      0,   // 未初始化
  OPENED:      1,   // open() 已调用
  HEADERS_RECEIVED: 2, // 收到响应头
  LOADING:     3,   // ↓ 正在下载响应体(交互中)
  DONE:        4    // 完成
};

[!question] 💡 思考 为什么 LOADING(3) 适合做"流式进度展示"而不是 DONE(4)?

Q38:AJAX 成功事件

项目 内容
❌ 你的答案 B(onreadystatechange)
✅ 正确答案 A(onload)
// 推荐方式:onload — 简洁明了
xhr.onload = function () {
  if (xhr.status === 200) {
    console.log(xhr.responseText);
  }
};

// 旧方式:onreadystatechange — 需要自行判断状态
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) { /*...*/ }
};

[!important] 记忆要点

  • onload:请求完整结束(等同于 readyState===4),仅区分成功/失败
  • onerror:网络级别失败(DNS 错误、断网等)
  • onreadystatechange:状态每变化一次都触发,需手动检查 readyState === 4

Q39:CORS 响应头

项目 内容
❌ 你的答案 D(Cross-Origin-Resource-Policy)
✅ 正确答案 A(Access-Control-Allow-Origin)

[!warning] 避坑 这是服务端返回的响应头,格式为 Access-Control-Allow-Origin: https://example.com。客户端不需要手动设置这个头部。

Q40:解析 JSON 响应的 API

项目 内容
❌ 你的答案 B(XML.parse())
✅ 正确答案 A(JSON.parse())

[!abstract] 冷知识 XHR 原生支持 responseType = 'json',此时 xhr.response 直接就是解析好的 JS 对象,无需手动 JSON.parse()。


二、HTTP 协议基础

Q51:HTTP 400 状态码

项目 内容
❌ 你的答案 A(请求方式错误)
✅ 正确答案 D(请求参数错误)

[!memory] HTTP 状态码速记表

graph LR
  A["2xx 成功"] --> A1["200 OK"]
  A --> A2["201 Created"]
  B["3xx 重定向"] --> B1["304 Not Modified"]
  C["4xx 客户端错误"] --> C1["400 Bad Request"]
  C --> C2["401 Unauthorized"]
  C --> C3["403 Forbidden"]
  C --> C4["404 Not Found"]
  D["5xx 服务端错误"] --> D1["500 Internal Server Error"]
  D --> D2["502 Bad Gateway"]

Q52:Content-Type 的作用

项目 内容
❌ 你的答案 D(响应的资源类型)
✅ 正确答案 A(请求体的类型)

[!example] 常见 Content-Type

  • application/json — JSON 数据(最常用)
  • application/x-www-form-urlencoded — 传统表单
  • multipart/form-data — 文件上传
  • text/html / text/css / image/png — 响应端

三、JavaScript 核心概念

Q07:JS 数据类型辨析

项目 内容
❌ 你的答案 A(RegExp)
✅ 正确答案 D(String)

[!question] 💡 思考 为什么 RegExp / Function / Array 属于引用类型(对象),而 String 是基本类型?

typeof /pattern/   // "object" → RegExp 是对象类型
typeof function(){} // "function" → Function 是对象类型
typeof []           // "object" → Array 是对象类型
typeof "hello"      // "string" → 基本类型!
typeof new String("a") // "object" → String 包装对象才是对象类型

Q06:值传递 vs 引用传递

项目 内容
❌ 你的答案 A(10)
✅ 正确答案 A(9)
let num = 9;
function fn(num) {
  num = num + 1;  // 修改的是函数局部参数,不影响外层
}
fn(num);
console.log(num);  // 9 —— 基本类型按值传递

[!example] 对比:引用类型的行为(Q14)

let arr = [1];
function fn(arr) {
  arr.push(3);  // 修改的是同一块堆内存
}
fn(arr);
console.log(arr);  // [1, 3]

Q23:一元加号 + 的类型转换

项目 内容
❌ 你的答案 D(string)
✅ 正确答案 B(number)
typeof +'136';  // "number"
// 等价于:Number('136') → 136
// '+' 作为一元运算符时,会将操作数转换为数字

Q13 & Q43 & Q44:事件循环(Event Loop)输出顺序

这三道题都在考同一个核心:同步 → Promise微任务 → setTimeout宏任务。

题目 ❌ 你的答案 ✅ 正确答案
Q13 D C(2→3→5→4→1)
Q43 D A(8,9,5,5,5,5,5)
Q44 D A(23541)

以 Q13 为例,执行过程分解:

[!abstract] Event Loop 执行流程

flowchart TD
  A["同步代码开始执行"] --> B["setTimeout 注册宏任务"]
  B --> C["Promise 立即执行"]
  C --> D["for 循环 resolve"]
  D --> E["console.log 5"]
  E --> F["同步代码结束"]
  F --> G["微任务 then"]
  G --> H["宏任务 setTimeout"]

[!tip] 记忆口诀 "同步先行,微任务跟进,宏任务殿后"

输出顺序始终是:2 → 3 → 5 → 4 → 1

对于 Q43(var 闭包陷阱):

console.log(8);            // 1. 同步输出 8
for (var i = 0; i < 5; i++) {
  // var 没有块级作用域,i 最终值为 5
  setTimeout(() => console.log(i), 1000 * i);
  // 5个定时器全部注册为宏任务
}
console.log(9);            // 2. 同步输出 9
// 3. 1秒后依次输出 5,5,5,5,5

Q27:对象引用赋值

项目 内容
❌ 你的答案 A('teal')
✅ 正确答案 B('red')
let obj1 = { uname: 'teal' };
let obj2 = obj1;             // 引用赋值,指向同一块内存
obj2.uname = 'red';
console.log(obj1.uname);     // 'red' ← obj1 也变了!

Q01:Axios 拦截器的问题

项目 内容
❌ 你的答案 D
✅ 正确答案 D(B和C都对)

[!note] 纠正说明 此题你答对了。关键两点:

  • token 过期应先尝试刷新,而非直接跳转登录
  • SPA 中应使用路由跳转(如 router.push('/login')),window.location.href 会触发整页刷新,破坏 SPA 体验

Q12:响应拦截器异常处理

项目 内容
❌ 你的答案 C
✅ 正确答案 C(两个回调位置写法)

[!note] 纠正说明 此题你答对了。注意签名顺序:use(onFulfilled, onRejected)——先成功回调,后失败回调。

Q100:Node.js 启用 ESM

项目 内容
❌ 你的答案 C(--experimental-modules)
✅ 正确答案 D(B和D均正确)

两种方法均可启用 ESM:

  1. package.json 中添加 "type": "module"
  2. 使用 .mjs 扩展名

[!warning] 注意 --experimental-modules 是 Node 12~13 的临时标志,Node 14+ 已移除,不再是推荐做法。


四、事件系统与 DOM/BOM

Q02:取消默认事件的正确方法

项目 内容
❌ 你的答案 C(preventDefault())
✅ 正确答案 C(preventDefault())

[!note] 纠正说明 此题你答对了。

  • preventDefault() → 阻止默认行为(如链接跳转、表单提交)
  • stopPropagation() → 阻止事件冒泡
  • cancelBubble = true → IE8 时代的旧写法

Q16:获取 CSS 样式的方法

项目 内容
❌ 你的答案 A(getElementStyle())
✅ 正确答案 B(getComputedStyle())
// 标准写法
const style = getComputedStyle(element);
console.log(style.fontSize);

// 兼容性写法(IE8-)
element.currentStyle?.fontSize;

Q17:TypeError 的产生场景

项目 内容
❌ 你的答案 A(未定义变量操作)
✅ 正确答案 B(将函数作为对象使用)
TypeError 的典型场景:
undefined.foo        → ReferenceError(不是 TypeError!)
fn()                 → TypeError(fn 不是函数却被当作函数调用)
new undefined()      → TypeError
'text'.split = 1     → TypeError(不可配置属性被修改)

[!question] 💡 思考 为什么访问 undefined.xxx 抛的是 ReferenceError 而不是 TypeError?

Q19:可继承的 CSS 属性

项目 内容
❌ 你的答案 D(line-height)
✅ 正确答案 C(border)

[!memory] CSS 继承规则速记 文本相关属性(color/font/line-height/letter-spacing)默认继承。 盒模型属性(border/margin/padding/width/height)不继承。

Q20:选择器优先级

项目 内容
❌ 你的答案 D(id)
✅ 正确答案 A(style(行内样式最高))

[!memory] CSS 优先级从高到低

!important > 行内 style > ID 选择器 > Class/属性/伪类 > 标签选择器 > 通配符

Q26:querySelector 选择第一个 box 类元素

项目 内容
❌ 你的答案 C
✅ 正确答案 C(document.querySelector('.box'))

[!note] 纠正说明 此题你答对了。注意:.box 中的点 . 表示类选择器,不加点 box 会被当作标签名 <box>。

Q30:事件委托中获得真实触发元素

项目 内容
❌ 你的答案 C(target.name)
✅ 正确答案 A(event.target.tagName)

Q31:阻止事件冒泡

项目 内容
❌ 你的答案 C(preventPropagation())
✅ 正确答案 B(event.stopPropagation())

[!warning] 避坑 DOM 规范中不存在 preventPropagation() 这个方法。容易和 preventDefault() 混淆。

Q59:文件上传编码类型

项目 内容
❌ 你的答案 A
✅ 正确答案 A(enctype="multipart/form-data")

[!note] 纠正说明 此题你答对了。只有文件上传时需要 multipart/form-data;普通表单用默认的 application/x-www-form-urlencoded 即可。

Q73:操作浏览器地址栏的对象

项目 内容
❌ 你的答案 A(navigator)
✅ 正确答案 D(location)

[!memory] BOM 四大对象区分

  • location:URL 信息(搜索 ?、哈希 #、跳转 assign/replace)
  • history:历史栈(back/forward/go)
  • navigator:浏览器信息(userAgent/platform)
  • screen:屏幕尺寸

Q105:teleport 组件的理解

项目 内容
❌ 你的答案 B
✅ 正确答案 C(可以条件性启用)

[!abstract] teleport 的关键特性

  • 传送的内容保持与原组件的数据绑定(响应式依然存在)
  • 可以通过 to 属性指定任意合法选择器(不限于 body)
  • 支持 :disabled 条件控制是否传送

Q107:Context 中修改 theme

项目 内容
❌ 你的答案 B
✅ 正确答案 B(需要将 setTheme 也传入 Context)

[!note] 纠正说明 此题你答对了。Context 只传值不传方法,子组件就无法修改父组件的状态。正确做法是把 [theme, setTheme] 一起放入 value 对象。


五、存储与定时器

Q33:localStorage 的限制

项目 内容
❌ 你的答案 A(存储任意类型)
✅ 正确答案 A(不能存储任意类型)

[!warning] localStorage 只能存字符串! 存入对象/数组会自动调用 .toString() 变成 [object Object]。正确做法:

localStorage.setItem('data', JSON.stringify({ a: 1 }));
const parsed = JSON.parse(localStorage.getItem('data'));

Q34:定时器描述的错误选项

项目 内容
❌ 你的答案 C
✅ 正确答案 C(并非所有定时器都会立即执行)

setTimeout(fn, 0) 不代表立刻执行,而是放入宏任务队列等待本轮同步代码结束后再执行。

Q35:classList 切换类的方法

项目 内容
❌ 你的答案 C
✅ 正确答案 C(toggleClass 不存在)

[!note] classList 的正确 API

方法 说明
add() 添加类
remove() 删除类
toggle() 切换(有则删,无则加)
contains() 是否包含
replace(old, new) 替换类名

[!warning] 注意区分 toggleClass() 不存在于 DOM API 中,正确方法是 classList.toggle()(没有 Class 中间那个大写字母)。

Q108:自定义 Hook 的请求问题

项目 内容
❌ 你的答案 B
✅ 正确答案 B(每次渲染都会发起请求)
// ❌ 错误:没有 useEffect 包裹
function useData(id) {
  fetch(`/api/data/${id}`).then(res => res.json()).then(setData);
}

// ✅ 正确:用 useEffect 控制时机
function useData(id) {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch(`/api/data/${id}`)
      .then(res => res.json())
      .then(setData);
  }, [id]);  // 依赖 id 变化才重新请求
}

六、框架相关

Vue 专题

Q01(provide/inject)& Q101

项目 内容
❌ 你的答案 A/C(父子通信 / props传递)
✅ 正确答案 B(跨多层传递)

[!abstract] provide/inject 适用场景

graph TD
  A["props drilling"] -->|"1-2层"| B["props 足够"]
  A -->|"3+层"| C["provide/inject 更优雅"]
  D["同层级兄弟"] --> E["提升状态到共同祖先"]
  F["全局共享"] --> G["Pinia / Vuex"]

Q102:reactive 解构导致响应式失效

项目 内容
❌ 你的答案 B
✅ 正确答案 B(解构会丢失响应式追踪)
const state = reactive({ count: 0 });

// ❌ 解构后失去响应式
const { count } = state;   // count 变成了普通数字
count++;                   // state.count 不变!

// ✅ 正确做法
const { count } = toRefs(state);  // toRefs 保留响应式
count.value++;                   // 同步更新 state.count

Q103:生命周期执行顺序

项目 内容
❌ 你的答案 B
✅ 正确答案 B(Child mounted → Parent mounted)

[!abstract] 挂载顺序

flowchart LR
  A["父 setup 执行"] --> B["子 setup 执行"]
  B --> C["子 template 渲染"]
  C --> D["子 onMounted 执行"]
  D --> E["父 template 渲染"]
  E --> F["父 onMounted 执行"]

Q106:API Key 泄露处理

项目 内容
❌ 你的答案 B
✅ 正确答案 B(在平台禁用并重新生成)

[!note] 纠正说明 此题你答对了。密码 ≠ API Key,更改密码无法撤销已泄漏的 Key。


React 专题

Q43(var 闭包)& Q44 & Q06 & Q14 & Q27:JavaScript 基础贯穿

这几道题其实在考同一个内核:JavaScript 的变量作用域和引用机制。

题目 考查点 你的答案 正确答案
Q43 var 循环闭包 D A
Q44 Promise + setTimeout D A
Q06 值传递 A A
Q14 引用传递 C C
Q27 引用赋值 A B

Q46:v-bind vs v-on

项目 内容
❌ 你的答案 C(v-on)
✅ 正确答案 A(v-bind(动态属性绑定))

Q62:useState 的作用

项目 内容
❌ 你的答案 B(定义 props)
✅ 正确答案 A(定义初始状态)

Q67:useEffect 清理副作用

项目 内容
❌ 你的答案 C(useState)
✅ 正确答案 A(返回一个函数)

Q70:React.memo 的作用

项目 内容
❌ 你的答案 D(比较 refs)
✅ 正确答案 A(比较 props,避免不必要重渲染)

Q72:子传父的实现方式

项目 内容
❌ 你的答案 C(状态提升)
✅ 正确答案 A(回调函数)

[!question] 💡 思考 "状态提升"和"回调函数"有什么区别?什么场景该用哪个?

Q84:触发重渲染的条件

项目 内容
❌ 你的答案 D(useRef变化)
✅ 正确答案 A(父组件状态变化)

[!warning] useRef 的变化不会触发重渲染——这正是它的价值所在。

Q98:浏览器原生支持的模块系统

项目 内容
❌ 你的答案 A(CommonJS)
✅ 正确答案 B(ESM)
<!-- 浏览器原生支持,通过 type="module" 开启 -->
<script type="module" src="./app.js"></script>

CommonJS 是 Node.js 的规范,浏览器需要打包工具(Webpack/Vite)才能使用。

Q99:ESM 中报错的导出语法

项目 内容
❌ 你的答案 D(export *)
✅ 正确答案 C(export = { a: 1 })

七、Node.js 与构建工具

Q09:浏览器页面加载事件

项目 内容
❌ 你的答案 A(DOMContentLoaded)
✅ 正确答案 B(load(HTML + 所有外部资源))

[!abstract] 两个关键事件对比

timeline
  title 页面加载事件时间线
  HTML解析完成 : DOMContentLoaded
  图片/CSS/JS加载完 : load

Q10:Node.js 能做什么

项目 内容
❌ 你的答案 A
✅ 正确答案 A(Node.js 不能操作 DOM)

Q49:执行 HTTP 请求的 Node 模块

项目 内容
❌ 你的答案 D(net)
✅ 正确答案 A(http)

Q50:FormData 添加键值对的方法

项目 内容
❌ 你的答案 D(set())
✅ 正确答案 A(append())

[!warning] 注意区分 Map 对象用 set(),但 FormData 用 append()。两者 API 不同。

Q53-56:Webpack 配置项速查

配置项 作用 你的答案
devtool 源代码映射 (sourcemap) ❌ A
externals 定义外部依赖(不打包) ✅ A
splitChunks 代码分割 ✅ A
resolve 解析模块路径/别名 ✅ A
optimization 优化打包 ✅ C

Q11:Node.js 内置模块

项目 内容
❌ 你的答案 D(dayjs)
✅ 正确答案 D(dayjs(第三方库,非内置))

Q57-58:Node.js 基础

题目 你的答案 正确答案
module.exports 导出公共接口 ✅ A
Node.js 是什么 — ✅ B

八、其他知识点

Q28:自定义 data-* 属性

项目 内容
❌ 你的答案 C(dataset 是函数)
✅ 正确答案 D(dataset 返回 DOMMap 对象,不是函数)

Q29:innerText vs innerHTML

项目 内容
❌ 你的答案 D
✅ 正确答案 D(两者作用不一致,innerHTML 解析标签)

[!note] 纠正说明 此题你答对了。innerText 只看纯文本,innerHTML 会解析并渲染 HTML 标签。

Q104:LLM 工作原理

项目 内容
❌ 你的答案 B
✅ 正确答案 B(下一个 token 的最大似然预测)

[!note] 纠正说明 此题你答对了。LLM 不是"理解"语义,而是基于概率统计预测下一个词。


高频考点速览

[!summary] 测试中暴露的共性薄弱环节

类别 高频考点 掌握要点
事件循环 同步/微任务/宏任务顺序 同步 → Promise.then → setTimeout
JavaScript 基础 值传递 vs 引用传递 基本类型传副本,引用类型传指针
事件系统 stopPropagation / preventDefault 冒泡 vs 默认行为,千万别混
CSS 优先级 & 继承规则 行内 > ID > Class > 标签;文本继承,盒模型不继承
HTTP 400/401/403/404/500 4x 客户端错,5x 服务端错
Axios 拦截器最佳实践 优先路由跳转、先刷新 token
Vue provide/inject 专为跨多层通信设计
Vue reactive 解构 用 toRefs 保留响应式
React useEffect 清理 return () => cleanup
React 状态不可变性 setList([newArr]) 而非 push+原引用
React useRef 不触发重渲染
模块系统 ESM vs CommonJS 浏览器原生 ESM,export/import
webpack devtool sourcemap 调试用,不是开发工具

关联笔记