前端2023年11月19日 18:07
React setState 是同步还是异步?原理是什么?`setState` 并非真正“异步”——它是**批量延迟执行**。调用 `setState` 时,React 把更新对象推入当前 Fiber 节点的 `updateQueue`(环形链表),然后调度一次重新渲染,而不是立即修改 state 和触发 DOM 更新。等调度机制在下一个工作单元执行时,才遍历 `updateQueue` 计算新 state 并渲染。
批量更新的核心逻辑:同一个事件循环内的多次 `setState`,只会产生一次渲染调度。合并发生在遍历 `updateQueue` 阶段——React 依次执行每个 update 的计算函数,得到最终 state,再进入 ren...前端2023年11月19日 18:21
浏览器渲染页面的过程是怎样的?浏览器从收到 HTML 到画出画面,走的是这条流水线:**DOM 树 → CSSOM 树 → Render 树 → Layout → Paint → Composite**。面试时把这六个词按顺序说出来,再展开每步做了什么,就够了。
1. **解析 HTML → DOM 树**:字节流 → 字符 → Token → 节点 → DOM 树。遇到 `<script>` 暂停解析,下载执行完 JS 再继续——因为 JS 可能改 DOM。CSS 和图片不阻塞 DOM 构建,但 **CSS 会阻塞后续 JS 执行**:JS 可能读 `getComputedStyle()`,浏览器必须等 CSSO...前端2023年6月10日 01:02
ES6 类继承中 super 关键字的作用是什么?`super` 在 ES6 类继承中有两种用法:**作为函数调用**和**作为对象引用**。核心要点是——`super()` 调用父类构造函数,`super.method()` 调用父类原型方法,`super.staticMethod()` 在静态方法中调用父类静态方法。
## super() 作为函数调用
在子类 `constructor` 中,`super()` 调用父类构造函数。ES6 的继承机制规定:父类负责创建 `this` 对象,子类负责在此基础上添加属性。因此 `super()` 必须在 `this` 之前调用,否则会抛出 `ReferenceError`。
```j...前端2023年11月19日 17:31
如何实现 Web 图片懒加载?面试官问:如何实现 Web 图片懒加载?
图片懒加载的核心思路:图片不在视口内时不加载,滚动到接近视口时再加载,减少首屏请求数和带宽消耗。
## 答案
现代前端有三种主流实现方式,按推荐优先级排列:
### 1. 原生 `loading="lazy"`(首选)
```html
<img src="image.jpg" loading="lazy" alt="描述文字" />
```
一行搞定。Chrome 76+、Edge、Firefox 均支持,Safari 15.4+ 也已支持。浏览器自动根据视口距离判断加载时机,无需 JS。
**关键细节**:对首屏内的图片不要加 `...前端2023年11月19日 18:08
Webpack 有哪些优化手段?Webpack 有哪些优化手段?
从构建速度和产物体积两个方向回答,面试中最常考察的优化点如下:
## 构建速度优化
### 1. 持久化缓存
```js
// webpack.config.js
module.exports = {
cache: {
type: 'filesystem', // Webpack 5 支持
buildDependencies: {
config: [__filename]
}
}
}
```
首次构建后缓存写入 `node_modules/.cache/webpack`,二次构建可减少 60%-80% 时...前端2023年11月21日 10:12
JavaScript 如何实现自定义事件?## 基本用法:CustomEvent 三步走
自定义事件的核心流程就三步:创建 → 监听 → 触发。
```javascript
// 1. 创建事件
const event = new CustomEvent('user-login', {
detail: { userId: 42, role: 'admin' }, // 携带数据
bubbles: true, // 是否冒泡
cancelable: true // 能否被 preventDefault() 取消
});
// 2. 监听
element.addEventListener('user-log...前端2023年11月21日 10:09
CSS 选择器的权重怎么计算?CSS 权重(Specificity)用四元组 (a, b, c, d) 表示,从左往右逐位比较,高位相同才比下一位:
| 位置 | 含义 | 示例 | 每个贡献值 |
|------|------|------|-----------|
| a | 行内样式 | style="" | 1 |
| b | ID 选择器 | #header | +1 |
| c | 类/属性/伪类 | .nav、[type="text"]、:hover | +1 |
| d | 标签/伪元素 | div、::before | +1 |
:::tip
通配符 * 、组合符(>、+、~、空格)不贡献权重。...前端2023年11月21日 10:19
什么是柯里化函数?JavaScript 中有哪些使用场景?## 什么是柯里化?
柯里化(Currying)是将一个接受多个参数的函数,转换成一系列每次只接受一个参数的函数。转换后的函数会逐步收集参数,直到参数齐全才执行原函数。
```javascript
// 普通函数
function add(a, b, c) {
return a + b + c;
}
add(1, 2, 3); // 6
// 柯里化后
function curryAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
curry...前端2023年11月21日 10:10
JavaScript 继承方式有哪几种?各自的优缺点是什么?JavaScript 的继承方式有以下七种,按演进顺序理解更容易记住:原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承、ES6 class extends。面试中重点掌握组合继承的问题和寄生组合继承的优化思路。
## 原型链继承
将子类的原型指向父类的实例:
```js
function Parent() {
this.name = 'parent';
this.colors = ['red', 'blue'];
}
Parent.prototype.getName = function() {
return this.name;
};
fun...前端2023年11月21日 10:35
什么是伪类和伪元素?它们之间有什么区别?伪类和伪元素都是 CSS 选择器的扩展机制,但本质不同:
**伪类(单冒号 `:`)**:选择 DOM 中**已有元素的某种状态**。元素本身存在,伪类只是在特定条件下"筛选"它。比如 `:hover` 选中的还是那个 `<a>` 元素,只不过它正处于鼠标悬停状态。
**伪元素(双冒号 `::`)**:在 DOM 树中**创建一个不存在的虚拟节点**,然后对这个虚拟节点施加样式。比如 `::before` 在元素内容前面插入一个匿名盒子,这个盒子在 HTML 源码里根本不存在。
用一个类比:伪类是给已有的人拍一张特定状态的照片(站着、坐着),伪元素则是凭空造出一个不存在的人再给他拍...