DrillLab
八股题库Question bank

105 道问答题,一道一卡105 questions, one card each

默认只显示问题 —— 先自己在心里答一遍,再展开对答案。答不上来就标「不会」,下次抽认卡会先抽它。Only the question shows by default. Answer it in your head first, then open the answer. Mark the ones you miss; the flashcard round puts those first.

0 / 105道自评过self-assessed
0Got it0模糊Shaky0不会No idea105还没做Not seen
正在读这台浏览器里的标记…Reading your marks from this browser…
标记不是打分,是给下一轮排队Marks are a queue, not a score

标「不会」的题会排到抽认卡最前面,标「会」的进低频池排最后。所以别客气 —— 觉得答得磕磕巴巴就标「模糊」。准备好了就去抽认卡“No idea” jumps to the front of the next round; “got it” drops to the back. So be honest — if it came out shaky, mark it shaky. Then go run a flashcard round.

题目Questions

筛出 38 道(共 105 道) · 第 4 / 4 页。38 of 105 questions · page 4 / 4.
JavaScriptJavaScript#283

Webpack 是怎么工作的

How does Webpack work

看答案Show answer

一句话:从入口出发递归分析所有 import, 建出一张依赖图, 路上用 loader 把各种文件转成 JS, 最后按规则打成若干个 bundle。

四个核心概念(必答):

  • entry—— 从哪开始找依赖。
  • output—— 打到哪里、叫什么名 (带 [contenthash] 做缓存)。
  • loader——把非 JS 转成 JSbabel-loader 转 JSX 和新语法、css-loader 让 CSS 能被importloader 是从右到左(从下到上)执行的, 这个细节常问。
  • plugin—— 在构建生命周期的各个钩子上干活, 能力比 loader 大得多 (生成 HTML、抽 CSS、压缩、分析体积)。

为什么需要打包(这才是问题的本质):浏览器早期不支持模块、 不认识 JSX 和 TS、 请求数多会慢; 打包解决的是模块化、转译、 合并压缩、以及 tree shaking

会追问:「Vite 为什么快?」—— 这题现在很常问。 开发时 Vite 不打包, 直接用浏览器原生 ESM 按需提供模块, 所以启动是常数时间, 不随项目变大而变慢; 依赖预构建用 esbuild(Go 写的,快一个量级); 生产才用 Rollup 打包。
Webpack 是「先全量打包再服务」, Vite 是「先服务再按需转换」—— 这一句就说到了根本区别。

In one line: start at the entry, walk every import recursively and build a dependency graph, push files through loaders to turn them into JS along the way, and emit a handful of bundles according to your rules.

Four core concepts you have to name:

  • entry — where the dependency walk starts.
  • output — where the bundles land and what they are called (with [contenthash] for caching).
  • loaderturns non-JS into JS. babel-loader handles JSX and new syntax, css-loader makes CSS importable. Loaders run right to left (bottom to top) — that detail gets asked a lot.
  • plugin — hooks into the build lifecycle and can do far more than a loader (generate HTML, extract CSS, minify, analyse bundle size).

Why bundling exists at all — that is the real question: early browsers had no modules, they do not understand JSX or TS, and a lot of requests is slow. Bundling buys you modularity, transpilation, merging and minifying, and tree shaking.

Follow-up: “Why is Vite fast?” — asked constantly now. In development Vite does not bundle; it serves modules on demand over the browser’s native ESM, so startup is constant time and does not degrade as the project grows. Dependency pre-bundling runs on esbuild (written in Go, an order of magnitude faster), and only production goes through Rollup.
Webpack bundles everything and then serves it; Vite serves first and transforms on demand — that single sentence gets at the fundamental difference.

JavaScriptJavaScript#387

fetch 和 axios 的区别

What is the difference between making server requests via fetch and axios?

看答案Show answer

一句话:fetch浏览器内置的, 很基础;axios 是第三方库, 把常用的事都替你做了。

fetchaxios
依赖,浏览器/Node 18+ 内置要装(约 13 KB)
4xx / 5xx不 reject, 要自己查 res.ok自动抛错
JSON要手动 await res.json()自动解析到 data
超时要自己配 AbortControllertimeout 一个选项
拦截器没有,要自己包一层内置(统一加 token、统一处理 401)
上传进度很麻烦支持
Node 里可用18+ 才有一直可以

「404 不 reject」是这题的核心考点, 也是真实 bug 的来源:不查res.ok 就会把错误页当数据渲染。从 axios 转过来的人最容易漏这一条, 因为 axios 会自己抛。

怎么选:简单项目、在意包体积、 或者只发几个请求 → fetch包一个自己的小 wrapper; 需要拦截器 / 统一错误处理 / 上传进度,或者要兼容老 Node → axios
更常见的现实答案:用TanStack Query / SWR管缓存和请求状态, 底下用哪个都行 —— 因为fetchaxios都不管缓存、去重、重试。 能这么答说明你想过分层。

In one line: fetch is built into the browser and very bare-bones; axios is a third-party library that does the routine work for you.

fetchaxios
DependencyNone, built into browsers and Node 18+Must be installed (about 13 KB)
4xx / 5xxDoes not reject; you check res.ok yourselfThrows for you
JSONYou call await res.json() by handParsed into data already
TimeoutWire up an AbortController yourselfOne timeout option
InterceptorsNone; wrap it yourselfBuilt in (attach a token everywhere, handle 401 in one place)
Upload progressPainfulSupported
Available in NodeOnly from 18Always has been

“404 does not reject” is the heart of this question, and a real source of bugs: skip the res.ok check and you render an error page as if it were data. People coming over from axios miss this one most often, because axios throws on their behalf.

How to choose: a small project, a tight bundle budget, or only a handful of requests → fetch with your own small wrapper. Interceptors, one place for error handling, upload progress, or an old Node to support → axios.
The more realistic answer: reach for TanStack Query or SWR to manage caching and request state, and whichever one sits underneath hardly matters — because neither fetch nor axios handles caching, deduplication or retries. Answering that way shows you have thought about the layers.

JavaScript两者的核心差别与自制 wrapperThe main difference, and a wrapper of your own示意Illustrative
1// fetch:404 也是「成功」,必须自己判
2const res = await fetch(url);
3if (!res.ok) throw new Error(`HTTP ${res.status}`); // ← 漏了这行就会出 bug
4const data = await res.json();
5
6// axios:非 2xx 自己抛,data 已经解析好
7const { data } = await axios.get(url);
8
9// 自己给 fetch 包一层,就能补上大部分差距
10async function request(url, opts = {}) {
11 const c = new AbortController();
12 const t = setTimeout(() => c.abort(), opts.timeout ?? 10000);
13 try {
14 const res = await fetch(url, { ...opts, signal: c.signal });
15 if (!res.ok) throw new Error(`HTTP ${res.status}`);
16 return await res.json();
17 } finally {
18 clearTimeout(t);
19 }
20}
1// fetch: a 404 also counts as "success", so you have to check it yourself
2const res = await fetch(url);
3if (!res.ok) throw new Error(`HTTP ${res.status}`); // ← leave this line out and you get a bug
4const data = await res.json();
5
6// axios: it throws on anything that is not 2xx, and data is already parsed
7const { data } = await axios.get(url);
8
9// Wrap fetch yourself and you close most of the gap
10async function request(url, opts = {}) {
11 const c = new AbortController();
12 const t = setTimeout(() => c.abort(), opts.timeout ?? 10000);
13 try {
14 const res = await fetch(url, { ...opts, signal: c.signal });
15 if (!res.ok) throw new Error(`HTTP ${res.status}`);
16 return await res.json();
17 } finally {
18 clearTimeout(t);
19 }
20}

这些题从哪来Where these come from

99 道来自面试题库 #269–#387;TypeScript 深度那 6 道是 DrillLab 自出的(senior 补强,卡片上有标注)。答案都是 DrillLab 写的,所以讲解里的代码块一律标「示意」。每道题都能点回它出处的那一节课。99 questions come from the interview bank (#269–#387); the 6 TypeScript deep-dive ones are DrillLab-made (marked on the card). All answers are written by DrillLab, so every code block here is labelled “demo”. Each card links back to the lesson it came from.