- Published on
前端面试系列一
- Authors
- Name
- Tszkong Cheng
一、请绘制一张九九乘法表

解法
<div id="wrapper"></div>
<script>
const table = document.getElementById('wrapper');
for (let i = 1; i < 9; i++) {
const row = document.createElement('div');
for (let j = 1; j <= i; j++) {
const cell = document.createElement('span')
cell.innerHTML = ``
row.appendChild(cell)
}
table.appendChild(row)
}
document.body.appendChild(table)
</script>
二、请说一下对宏任务、微任务、事件循环的了解
1. 事件循环(Event Loop)
JavaScript 是单线程语言,为了能同时处理异步任务,引入了事件循环机制。 事件循环的核心逻辑是:
不断从任务队列中取出任务,放入主线程执行。
主要流程如下:
- 执行主线程中的同步任务(Script 脚本)。
- 执行完后,开始进入事件循环。
- 检查是否有微任务队列(Microtask Queue)中的任务,有则全部执行。
- 然后从宏任务队列(Macrotask Queue)中取出一个任务执行。
- 重复步骤 3~4,直到宏任务队列为空。
2. 宏任务(Macrotask)
宏任务(Macrotask)指的都是执行环境为浏览器的异步任务,比如:
- setTimeout
- setInterval
- setImmediate(Node.js)
- I/O
- requestAnimationFrame
3. 微任务(Microtask)
微任务(Microtask)指的都是执行环境为 Promise 的异步任务,比如:
- Promise.then / catch / finally
- queueMicrotask(原生 API)
4. 举例子说明执行顺序
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => {
console.log('3');
});
}, 0);
Promise.resolve().then(() => {
console.log('4');
setTimeout(() => {
console.log('5');
}, 0);
}).then(() => {
console.log('6');
})
setTimeout(() => {
console.log('7');
}, 0);
console.log('8');
执行顺序为: 1 8 4 6 2 3 7 5
三、回流(Reflow)、重绘(Rapaint)、重排(Layout)
回流/重排是同一概念,叫法不同。含义是:当页面中的元素尺寸、位置或结构发生变化,浏览器会重新计算元素的几何属性(位置、宽高等)。
触发时机:
- 添加或者删除 DOM 元素;
- 改变元素的位置;
- 改变元素的尺寸大小;
- 改变字体大小;
- 改变元素的显示状态(display: none / block)。
性能消耗: ⚠️ 回流开销较大,可能影响整个 DOM 树或其一部分。
重绘:当元素的样式发生改变,但没有影响布局(几何形状),只需要重新渲染外观样式时,会发生重绘。
触发时机:
- 改变元素颜色;
- 改变元素阴影;
- 边框样式等。
性能消耗: ✅ 重绘开销较小,但频繁发生也会影响性能。
关系对比
项目 | 回流 | 重绘 |
---|---|---|
影响内容 | 结构、样式 | 样式(不影响结构) |
触发时机 | 改变元素位置、尺寸、结构、样式 | 改变元素颜色、阴影、边框样式等 |
性能消耗 | 大 | 小 |
是否会引发 | 通常会引发重绘 | 不引发回流 |
如何避免或减少回流重绘:
- 避免或减少 DOM 操作次数;
- 避免逐条修改样式,使用 class 切换/设置 style;
- 隐藏元素再操作,隐藏元素不参与回流,等于“离线处理”;
- 使用虚拟 DOM或合适的框架;
- 动画中避免使用 top/left/width/height 等属性,使用 transform 和 opacity。
四、请说下 Vue 响应式
1. Vue 2 与 Vue 3 响应式实现原理对比
特性 | Vue 2 | Vue 3 |
---|---|---|
实现方式 | Object.defineProperty | Proxy |
支持的数据类型 | 仅对象、数组(不支持 Map/Set) | 所有对象类型(含 Map、Set 等) |
动态属性 | 手动 Vue.set() 添加响应式 | 自动响应 |
数组变异监听 | 依靠重写原型方法(push 等) | Proxy 直接拦截 |
嵌套对象 | 仅支持第一层 | 支持任意层 |
深层嵌套响应 | 初始化时递归遍历每个属性 | 按需惰性代理,性能更优 |
依赖追踪方式 | 使用 Watcher + Dep | 使用 effect + reactiveMap |
性能 | 初始化慢,依赖管理复杂 | 响应性更快、更灵活 |
缺陷 |
2. Vue 2 的主要缺陷
- 无法监听新增/删除属性;
- 数组索引和 length 无法被响应式监听;
- 初始化时递归遍历所有属性,性能差;
- 对象解构会失去响应式。