字节一面
一、字节跳动
1、自我介绍
2、React用得多还是Vue用得多?
我之前在学校阶段用 Vue 比较多,因为很多课程项目是基于 Vue 做的。后来在实习以及之后的项目中主要使用的是 React,目前主要技术栈是 React + TypeScript。React 的函数式组件和 Hooks 体系让我在状态管理和逻辑复用方面感觉更灵活,所以现在用 React 会更多一些。
3、React用的什么版本?React19有哪些新特性?
我主要使用的是 React 18。React18比较重要的特性包括并发渲染、自动批处理、useTransition 等。
React19新增的一些能力主要包括:
- Actions:简化表单提交和异步状态更新逻辑
- use hook:可以直接读取 Promise 或 Context 数据
- Server Components 更稳定:更好支持服务端组件
- 缓存机制增强:例如
cache()API - 更好的错误处理与资源加载能力 整体上 React19 更加强化了 服务端渲染和数据获取能力。
4、React常用hooks有哪些?
常用的 Hooks 主要包括:
- useState:用于在函数组件中管理状态
- useEffect:处理副作用,比如请求数据、订阅事件等
- useRef:获取 DOM 节点或者保存可变值
- useMemo:缓存计算结果,避免重复计算
- useCallback:缓存函数引用,避免子组件重复渲染
- useContext:跨组件传递数据
除此之外还有一些进阶的 Hooks,比如 useReducer、useLayoutEffect、useTransition 等。
5、setState之后React做了什么?
当调用 setState 或 useState 的更新函数后,大致流程是:
- React 会先 创建新的 Fiber 节点并标记更新
- 进入 调度阶段(Scheduler) ,React会根据优先级调度更新任务
- 进入 Reconciliation 阶段(Diff阶段) ,比较新旧虚拟 DOM
- 找出需要更新的节点
- 进入 Commit阶段,把变更真正应用到真实 DOM 上
在 Commit 阶段还会执行:
- DOM 更新
- layout effect
- effect
6、React为什么只更新部分DOM?React Diff算法是什么?
React之所以只更新部分 DOM,是因为使用了 虚拟 DOM + Diff 算法。
React在状态变化后,会生成一棵新的虚拟DOM树,然后与旧的虚拟DOM进行比较,通过 Diff 算法找出发生变化的节点,只更新这些节点,而不是整棵DOM树。
React Diff算法的核心原则有三个:
- 只比较同一层级的节点,不同层级直接替换
- 如果节点类型不同,直接销毁旧节点并创建新节点
- 列表节点通过 key 来进行优化比较
这样可以把时间复杂度从 O(n³) 优化到 O(n)。
7、React什么时候复用节点?key的作用是什么?
React在 Diff 过程中,如果满足以下条件,就会复用节点:
- 节点类型相同,例如都是
div - key 值相同
如果 key 不同,React 会认为是新的节点,从而重新创建。
key 的作用主要是:
- 唯一标识列表元素
- 帮助 React 在 Diff 过程中识别节点
- 提高列表更新效率,减少不必要的 DOM 操作
通常在列表渲染时都会使用稳定的唯一 key,比如 id。
8、浏览器页面渲染流程是什么?HTML解析过程中遇到JS会发生什么?
浏览器渲染流程大致如下:
- 浏览器解析 HTML,生成 DOM Tree
- 解析 CSS,生成 CSSOM Tree
- DOM Tree 和 CSSOM Tree 合并生成 Render Tree
- 进行 Layout(布局) ,计算元素的位置和大小
- 进行 Paint(绘制) ,绘制页面内容
- 最后进行 Composite(合成) ,由 GPU 合成最终页面
如果在 HTML 解析过程中遇到 普通的 script 标签,浏览器会:
- 暂停 HTML 解析
- 下载并执行 JS
- JS执行完后再继续解析 HTML
原因是 JavaScript 可能会修改 DOM 结构,所以浏览器需要保证执行顺序。
9、HTTP有哪些版本?HTTP2有什么特点?HTTP3为什么更快?TCP和UDP有什么区别?
HTTP常见版本有:
- HTTP1.0
- HTTP1.1
- HTTP2
- HTTP3
HTTP2主要特点包括:
- 二进制分帧
- 多路复用:一个连接可以并发多个请求
- 头部压缩(HPACK)
- Server Push:服务器可以主动推送资源
HTTP3相比HTTP2更快的原因是:
HTTP3基于 QUIC协议,而QUIC是基于 UDP 实现的。
优点包括:
- 减少连接建立时间
- 支持 0-RTT
- 避免 TCP 队头阻塞问题
- 连接迁移能力更好
TCP和UDP的区别:
TCP是 面向连接、可靠传输的协议,需要三次握手,保证数据完整性。
UDP是 无连接协议,不保证数据可靠,但传输速度更快,延迟更低。
10、防抖和节流
import React, { useState, useRef } from "react";
// 防抖function debounce(fn, delay) {let timer = null;return function (...args) {if (timer) clearTimeout(timer);timer = setTimeout(() => {fn.apply(this, args);}, delay);};}
// 节流function throttle(fn, delay) {let lastTime = 0;return function (...args) {const now = Date.now();if (now - lastTime > delay) {fn.apply(this, args);lastTime = now;}};}
export default function Search() {const [value, setValue] = useState("");
const request = (v) => {console.log("search:", v);// 这里可以调用真实接口};
const debounceSearch = useRef(debounce(request, 500));const throttleSearch = useRef(throttle(request, 2000));
const handleChange = (e) => {const v = e.target.value;setValue(v);
// 防抖:停止输入后触发 debounceSearch.current(v); // 节流:持续输入也会每2秒触发一次 throttleSearch.current(v);
};
return (<inputvalue={value}onChange={handleChange}placeholder="请输入搜索内容"/>);}
11、TS工具类型
| 构造对象类型 |
|
| 选择部分属性 |
|
| 删除属性 |
|
| 所有属性变可选 |
|
| 所有属性变必填 |
|
| 所有属性只读 |
|
12、算法
判断一个字符串是不是 **累加数字符串**: - 从**前两个数字**开始 - 后面每一个数 = 前面**相邻两个数之和** - 整个字符串要**刚好分割**成这样的数列,不能剩、不能缺 例子(对的):`"199100199"`分割:`1, 99, 100, 199`1+99=100,99+100=199
function isAdditiveNumber(num) {
const n = num.length
for(let i = 1; i < n; i++){
for(let j = i + 1; j < n; j++){
let a = BigInt(num.slice(0,i))
let b = BigInt(num.slice(i,j))
let k = j
while(k < n){
let sum = a + b
let s = sum.toString()
if(num.slice(k, k + s.length) !== s){
break
}
k += s.length
a = b
b = sum
}
if(k === n){
return true
}
}
}
return false
}
查看9道真题和解析