2025-08-19 模拟面试(二)
一、JavaScript 深度考察
如果遇到一段 JavaScript 代码执行缓慢,你会如何系统性地分析和优化?
- 优先通过 Chrome Dev tools 来查看该段代码,可以查找到比较耗时的调用栈,长任务,同时也可以在关键代码处添加 console.time 来查看代码具体耗时
- 可以查看内存快照,排查有没有可能导致内存泄露的代码,主要观察未被释放的对象
- 必要时可以把代码放到 Web Worker 里执行,减少主线程的影响
浏览器中 setTimeout(fn, 0) 和 Promise.resolve().then(fn) 的执行顺序差异是什么?背后的优先级机制如何设计? then 先执行,setTimeout 后执行。then 是微任务,而 setTimeout 是宏任务,在任务队列里的优先级是微任务优先 浏览器的事件循环主要按照下面的顺序来执行
1. 执行一个 Macrotask(如 script 脚本、setTimeout、UI 渲染等) ↓ 2. 执行所有 Microtasks(如 Promise.then、MutationObserver) ↓ 3. 必要时渲染页面(requestAnimationFrame) ↓ 4. 取下一个 Macrotask 执行(循环)
如何实现一个支持并发数控制的异步任务调度器(如最多同时执行 3 个任务)?
class Scheduler {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency;
this.activeCount = 0;
this.queue = [];
}
add(task) {
return new Promise((resolve, reject) => {
const taskWrapper = () => {
this.activeCount++;
task()
.then(resolve, reject)
.finally(() => {
this.activeCount--;
this._runNext();
});
};
if (this.activeCount < this.maxConcurrency) {
taskWrapper();
} else {
this.queue.push(taskWrapper);
}
});
}
_runNext() {
if (this.queue.length > 0 && this.activeCount < this.maxConcurrency) {
const nextTask = this.queue.shift();
nextTask();
}
}
}
- 如何通过 Tree Shaking 减少打包体积?列举实际项目中导致 Tree Shaking 失效的常见陷阱。
“Tree Shaking 依赖三个关键条件:
- 使用 ESM 规范的 import/export;
- 生产环境启用压缩和 usedExports;
- 第三方库声明 sideEffects: false。
我曾遇到因 Babel 转译 CommonJS 导致失效的问题,通过配置 { modules: false } 解决。另一个案例是 Lodash 未使用 ESM 版本,改用 lodash-es 后体积减少 60%。”