面试

面试知识点汇总(TreeShaking/性能优化等)

#life / work #type / resource #status / growing #topic / interview

[!info] related notes

面试


入口


Rollup

Rollup 是一款专注于 JavaScript 模块打包 的工具,由 Rich Harris(Svelte 作者)开发。它的设计理念与 Webpack 有显著不同,更强调 轻量、高效和面向未来的模块化代码。

核心设计理念:

  • 面向 ESM
  • Tree Shaking 优先
  • 简单高效
  • 适合库/框架开发

核心特性:

  • Tree Shaking
  • 输出格式灵活
  • 插件系统
  • 代码分割

ref 和 reactive

特性refreactive
数据类型所有类型仅对象类型
访问方式.value(模板自动解包)直接访问属性
实现原理RefImpl + 内部调用 reactiveProxy 代理
对象替换支持不支持
深层监听需显式启用 deep: true默认支持
适用场景基本类型、灵活替换对象复杂对象、嵌套结构

Vite 和 Webpack

Vite:

  • 开发环境无需打包,速度快
  • 生产环境使用 Rollup 打包,支持 Tree Shaking、代码分割等优化
  • 热更新效率高

Webpack:

  • 全程打包
  • 成熟的生态系统,支持复杂的代码分割、插件扩展和旧浏览器兼容。

docker 与 虚拟机 的区别

docker

基于容器技术,共享宿主机的操作系统内核
通过命名空间(Namespace)和控制组(Cgroup)实现资源隔离
容器本质上是宿主机的进程
资源利用率高(硬件利用率可达60%-80%)
启动速度秒级
镜像体积小(通常为MB级)
进程级隔离,安全性较弱

典型应用场景:

  • 开发环境一致
  • 微服务架构
  • 跨平台应用分发
  • 临时测试环境

虚拟机

Hypervisor 虚拟化硬件
运行完整操作系统
资源消耗大
启动分钟级
镜像体积大
操作系统级隔离

SSR 应用

优点:

  • SEO 友好
    搜索引擎爬虫可以直接抓取服务端生成的完整HTML内容,无需依赖客户端JavaScript执行,显著提升搜索引擎收录效果
  • 首屏加载速度快
    服务器直接返回渲染后的 HTML
  • 低端设备兼容性
  • 内容一致性

问题:

  • 服务器性能压力
  • 开发复杂度
  • 安全风险
  • 流失渲染与性能优化
  • 部署与运维成本

js 有哪些 worker(Web Worker)

Web Worker是HTML5标准的一部分,允许在主线程外创建独立的后台线程(Worker线程)。这些线程与主线程并行运行,不共享内存和DOM,但可通过消息传递机制(postMessage和onmessage)进行通信。

JavaScript提供了多种 Worker 机制来实现多线程编程

  • Web Workers / Dedicated Workers(专用Worker):
    最基本的Worker类型,由主线程创建并专属于创建它的脚本
    无法访问DOM,通过postMessage与主线程通信
    适用于CPU密集型计算任务
  • Shared Workers(共享Worker):
    可以被多个浏览上下文(不同窗口、iframe等)共享
    适用于需要跨窗口/标签页共享数据和状态的场景
  • Service Workers:
    主要用作网络代理,可拦截和处理网络请求
  • Worklets:
    轻量级专用Worker,用于扩展渲染管道
  • Node.js中的Worker Threads:
    允许在Node.js中使用真正的多线程

worker 通信:

  • 通信机制
    结构化克隆
    共享内存
  • 使用限制
    无法操作 DOM
    同源策略
    生命周期管理

Electron 底层有几个线程

  • 主进程
  • 渲染进程
  • GPU 进程
  • 插件进程
  • 实用程序进程

设置存储时间:

  • expires
    绝对时间
  • max-age
    相对时间

存储位置:
未设置过期时间:会话 Cookie(内存中,关闭浏览器失效)。
设置过期时间:持久化 Cookie(硬盘中)。

localStorage

使用 localStorage.clear() 方法可以一次性清空当前域名下的所有 localStorage 数据
通过 localStorage.removeItem(key) 删除特定键值对
使用函数模拟定期清除

场景:

  • 用户数据持久化、偏好设置
  • 本地缓存、性能优化
  • 离线应用程序支持
  • 跨页面数据传递
  • 用户登录状态与身份验证
  • 表单数据自动填充
  • 跨标签页通信(监听 storage 事件)

PWA

渐进式增强(Progressive Enhancement)
关键技术组件:

  • Service Worker
    这是PWA的核心技术之一,负责离线缓存、推送通知、后台同步等功能。Service Worker是一段独立的JavaScript脚本,可以在后台处理网络请求,缓存数据和推送通知
  • Web App Manifest
    一个JSON文件,用于描述PWA应用的名称、图标、启动URL等信息,让浏览器可以将Web应用添加到主屏幕
  • HTTPS
    PWA必须通过HTTPS协议提供服务,确保用户数据的安全
  • Push API
    用于向用户发送推送通知
  • Cache API
    用于缓存静态资源

工作原理:

  • 拦截网络请求
    Service Worker可以拦截应用发出的所有HTTP请求
  • 缓存策略
    开发者可以自定义缓存策略,决定哪些资源应该被缓存以及如何响应缓存和网络请求
  • 离线支持
  • 后台同步

响应式设计的实现方式

响应式设计(Responsive Web Design, RWD)的核心是通过动态调整布局、内容和功能,使网页适配不同设备的屏幕尺寸和分辨率。

关键技术:

  • 流式布局
    使用百分比、vw/vh等相对单位替代固定像素,使元素尺寸随容器或视口变化。
  • 媒体查询
    通过CSS检测设备特性(如屏幕宽度、方向),应用不同的样式规则。
  • 弹性媒体
    图片和视频使用max-width: 100%或srcset属性,按需加载适配尺寸的资源。

前端工程化

  • 性能优化
  • RestFul API
  • 虚拟DOM、真实DOM

Tree Sharking

Tree Shaking(摇树优化)是一种用于优化 JavaScript 应用的静态代码分析技术,其核心目标是通过移除未使用的代码(即“死代码”)来减小最终打包文件的体积,从而提升应用加载速度和运行性能。这一概念最早由 Rollup 提出,现已成为现代前端构建工具(如 Webpack、Rollup、Vite 等)的标配功能。

核心原理:

  • 基于 ES6 模块的静态分析
    Tree Shaking 依赖于 ES6 模块(ESM)的静态结构特性(import/export),因为 ESM 的依赖关系在编译时即可确定,而非像 CommonJS 模块那样动态解析。这使得构建工具能够通过抽象语法树(AST)分析代码的导出与引用关系,精确识别未使用的模块或变量。
    若模块导出了 A 和 B,但仅 A 被其他模块引用,则 B 会被移除。
  • 死代码消除(DCE)的进阶形式
    传统 DCE 仅移除不可能执行的代码(如未调用的函数),而 Tree Shaking 更关注未引用的模块或导出值。
  • 与副作用(Side Effects)的关联
    若模块包含副作用(如修改全局变量、立即执行函数等),Tree Shaking 会保留这些代码以避免破坏程序逻辑。开发者可通过 package.json 的 “sideEffects” 字段显式标记这类模块(如 CSS 文件)。

Vue

  • Vue2、Vue3区别

React

  1. 你知道react的fiber架构吗?hook-useFiber
  2. React用函数式组件怎么模拟出生命周期
  3. useLayoutEffect和useEffect有什么区别

作者:想去夏威夷的土拨鼠在攒经验 链接:https://www.nowcoder.com/feed/main/detail/39249e4d6def4f15bd1c7400f927f37b?sourceSSR=enterprise 来源:牛客网

浏览器

  • 浏览器缓存机制
  • 浏览器两个Tab页之间要怎么跨页面通信
  • 浏览器垃圾回收机制

场景

  • 在做大文件分片上传的时候,每一个文件的唯一标识要怎么去获得呢?

算法

  • 链表反转
  • 最长公共子序列
  • dfs找最大岛屿
  • 找最长不重复子串

计算机网络

https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md

TCP的三次握手

  • 流程
  • 半连接和全连接
  • 为什么要三次握手
  • 三次握手可以携带数据吗

TCP 的四次挥手

  • 流程
  • 为什么要四次挥手
  • 能不能合并第二次和第三次
  • 为什么第四次挥手客户端需要等待 2*MSL(报文段最长寿命)时间后才进入 CLOSED 状态

TCP 传输可靠性保障

  • 如何保障
  • 流量控制
  • 拥塞控制
  • ARQ 协议
  • 超时重传

HTTP/0.9 最初想法是将文档存在服务器中,我们只需要从服务器获取存档
所以只有 GET,也没有请求头,并且请求完连接就断了

HTTP 1.0 和 HTTP 2.0 有什么区别

HTTP/1.0

  • 增加了 HEAD、POST 等新方法
  • 增加了响应状态码
  • 引入了头部(请求头、响应头)
  • 在请求中加入了 HTTP 版本号
  • 引入了 Content-Type, 使传输数据不再局限于文本

HTTP/1.1

  • 新增连接管理(keepalive),允许持久连接。
  • 支持 pipeline ,无需等待前面的请求响应,即可发送第二次请求。
  • 允许响应数据分块,即响应的时候不标明 Content-Length,客户端就无法断开连接,直到收到服务端的 EOF ,利于大文件传输
  • 新增缓存的控制和管理
  • 加入 Host 头,用在一台机子部署多个主机,多个域名解析又是同一个 IP,此时加入 Host 头就可以判断要访问哪个主机

HTTP/2

  • 变为二进制协议,不再是纯文本
  • 支持一个 TCP 连接发起多请求,移除了 pipeline
  • 利用 HPACK 压缩头部,减少数据传输量
  • 允许服务端主动推送数据

HTTP 2.0 和 3.0 有什么区别?

  • 基于UDP协议
  • 支持1-RTT 或 0-RTT 连接
  • 多路复用+轮询
  • 更高效的 QPACK 头部压缩算法
  • 连接迁移
  • 错误恢复
  • 整个数据包加密

常见的 HTTP 状态码有哪些?

HTTP 请求包含哪些内容,请求头和请求体有哪些类型?

HTTP 中 GET 和 POST 的区别是什么?

  • 语义
  • 幂等
  • 请求参数位置
  • 安全性
  • 缓存

WebSocket 与 HTTP 有什么区别?

  • WebSocket 也是一个应用层的协议,基于 TCP。
  • 支持实时双向通信
  • 协议前缀
  • 通信数据格式较轻量
  • 支持扩展

服务端是如何解析 HTTP 请求的数据?(考察 HTTP 请求格式的了解程度)

  • 接收请求
  • 解析请求行
  • 解析请求头
  • 处理请求题
  • 提取查询参数和路径参数
  • 处理Cookie和会话
  • 路由和业务逻辑处理
  • 生成响应
  • 发送响应并关闭连接

TCP 的粘包和拆包能说说吗? TCP 是面向字节流的协议,他只保证数据可靠传输,不维护消息边界。

粘包
定义:
多个数据包被合并成一个 TCP 段发送,接收方一次性读取到多个包的数据。
原因:
发送方:Nagle 算法(默认启用)会合并多个小数据包以提高网络效率。
接收方:缓冲区数据堆积,导致多个包被一次性读取。
拆包
定义:
一个数据包被拆分成多个 TCP 段发送,接收方需要多次读取才能拼凑完整数据。
原因:
发送方:数据包超过 MSS(Maximum Segment Size,通常 1460 字节)。
接收方:缓冲区大小不足,导致部分数据被截断。

解决方法:

  • 固定消息长度,不足补充\0
  • 使用特殊分隔符标记结束
  • 消息头写消息长度,消息体存储数据

TCP 初始序列号 ISN 怎么取值的? ISN 的基本要求:
- 唯一性:防止旧连接的延迟报文被误认为新连接的数据
- 不可预测性:防止攻击者猜测序列号并发起会话劫持
- 均匀分布:充分利用 32 位序列号空间(约 40 亿个可能)
现代安全算法:结合时间、连接信息和密码学哈希

除了四次挥手,还有什么方法断开连接?

  • RST

TCP 超时重传机制是为了解决什么问题? 网络通信中的数据包丢失问题

TCP 中何时会出现 RST(reset)报文? 连接建立阶段:
目标端口为监听
队列满
连接终止阶段:
强制终止连接
应用层主动终止(进程崩溃)
TIME-WAIT 状态终止 中间设备、安全策略
RST 的设计初衷是处理异常

TCP 的 SACK 的引入是为了解决什么问题? 选择性确认,接收方通过 SACK 选项告知发送方已收到的非连续数据块,避免重复传输

ARP 和 RARP 分别是什么?有什么区别? ARP(Address Resolution Protocol,地址解析协议)和 RARP(Reverse Address Resolution Protocol,逆地址解析协议) JWT Token 能说说吗?
JWT

常见的登录鉴权方式有哪些?各自的优缺点是?

HTTP 与 HTTPS 的区别

核心区别

特性HTTPHTTPS
安全性明文传输,无加密通过 SSL/TLS 加密数据,防窃听和篡改
默认端口80443
协议栈HTTP → TCPHTTP → SSL/TLS → TCP
证书无需证书需 CA 颁发的数字证书,验证服务器身份
性能无加密开销,理论更快加密/解密带来轻微延迟(现代优化后影响小)
浏览器标记标记为“不安全”显示安全锁图标
SEO无优势搜索引擎优先索引

详细说明

  1. 加密机制

    • HTTPS 使用混合加密:
      • 握手阶段:非对称加密(如 RSA)交换密钥。
      • 传输阶段:对称加密(如 AES)加密数据。
  2. 应用场景

    • HTTP:静态内容(如新闻、博客)。
    • HTTPS:登录、支付、隐私数据(如银行、电商)。
  3. 风险提示

    • 即使启用 HTTPS,若页面内混用 HTTP 资源(如脚本、图片),仍会触发浏览器警告(Mixed Content)。

为什么选择 HTTPS?

  • 用户信任(避免“不安全”提示)。
  • 符合 GDPR 等隐私法规要求。
  • 防止运营商劫持或广告注入。

TCP 和 UDP 的区别

TCP 提供面向连接的(三次握手)、可靠的(序列号、确认应答、超时重传)数据传输。
UDP 提供无连接的、尽最大努力的数据传输服务

  • 传输速率 TCP 要建立连接和维护可靠性机制,传输速率相对较低
  • 流量控制
    TCP 有流量控制和拥塞控制机制,能根据网络状态调整传输速率
    UDP 没有流量控制,以固定速率发送数据
  • 通信模式
    TCP 支持点对点通信
    UDP 支持一对一、一对多、多对多、多对一
  • 首部开销
    TCP 首部较大,至少 20 字节
    UDP 首部 8 字节
  • 应用场景
    TCP (高可靠传输):HTTP、FTP、SMTP
    UDP (高实时性):视频会议、游戏、DNS 查询

TCP 流量控制机制

TCP流量控制是一种端到端的协调机制,主要目的是防止发送方发送数据过快,导致接收方来不及接收处理,从而造成数据丢失。其核心是解决发送方与接收方速度不匹配的问题,确保接收方的缓冲区不会溢出。

滑动窗口机制:

  • 接收窗口(rwnd)
    接收方通过TCP头部中的Window字段告知发送方自己当前可用的缓冲区空间大小(单位字节)
  • 发送窗口
    发送方实际可发送的数据量取接收窗口和自身拥塞窗口(cwnd)的较小值
  • 动态调整
    当接收方应用程序读取数据后,接收窗口会增大并通过ACK通知发送方;当接收方处理不及时导致缓冲区填满时,会减小窗口值甚至设为0
关键问题

零窗口死锁问题

  • TCP 使用持续计时器,发送方定期发送 1 字节 的窗口探测报文查询最新窗口大小

糊涂窗口综合征

  • 问题描述:
    当接收方频繁通告小窗口时,会导致大量小包传输,降低效率
  • 解决方案:
    Nagle算法(发送方累积小数据)或接收方延迟通告小窗口

浏览器

Session、Cookie、Token 的区别

Cookie:
存储在客户端的小型文本文件(通常<=4KB)
服务器通过 Set-Cookie 响应头设置,浏览器后续请求自动携带
可能被 XSS 或 CSRF 攻击窃取,可通过HttpOnly、Secure等属性提升安全性
不可跨域(除非设置domain)
保持用户登录状态、记住用户偏好设置等

Session:
存储在服务端,客户端仅保存 Session ID
服务器创建会话并生成唯一Session ID返回给客户端,客户端后续请求携带此ID
相对安全(数据在服务端),但需防范Session ID泄露
分布式环境下需要特殊处理(如Session共享)
需要跟踪用户状态的场景,如购物车、表单提交等

Token:
存储在客户端(如LocalStorage、Cookie或移动端本地存储),服务端不保存Token本身
服务器验证用户身份后生成Token返回,客户端后续请求在Header中携带此Token
通常使用加密技术生成,较安全,但一旦签发难以主动失效
API访问控制、单点登录(SSO)等

SSL/TLS协议

SSL,Secure Sockets Layer
主要用于解决 HTTP 明文传输的安全风险
TLS,Transport Layer Security
SSL3.0 改进并标准化为 TLS1.0,逐渐取代 SSL

SSL/TLS协议分为两层:

  • 记录协议层
    作用:对上层数据分块、压缩、加密,并附加MAC值保证完整性
    加密方式:采用对称加密(如AES)结合CBC模式,初始化向量(IV)由主密钥生成。
  • 握手协议层

TLS握手流程

  1. ClientHello
    客户端发送支持的TLS版本、随机数(Client Random)、密码套件列表(如TLS_AES_256_GCM_SHA384)和压缩方法
  2. ServerHello
  3. 密钥交换与验证
  4. 完成握手

HTTP

版本改动

版本协议层关键特性改进点局限性
HTTP/1.0基于 TCP- 短连接(每次请求需新建 TCP 连接)
- 支持缓存(Expires/Last-Modified)
- 无 Host 头字段
首次标准化 HTTP 协议,支持多种数据类型(如 HTML、图片)- 高延迟(频繁连接/断开)
- 队头阻塞(请求按顺序处理)
HTTP/1.1基于 TCP- 默认长连接(Keep-Alive)
- 管道化传输(理论支持,默认关闭)
- 断点续传(Range 头)
- Host 头支持虚拟主机
- 减少 TCP 握手开销
- 支持部分资源请求
- 响应队头阻塞(服务器按顺序返回)
- 明文传输,安全性低
HTTP/2.0基于 TCP + TLS- 二进制分帧(Header/Data Frame)
- 多路复用(单连接并发请求)
- 头部压缩(HPACK)
- 服务端推送(Server Push)
- 提升传输效率与带宽利用率
- 解决应用层队头阻塞
- 仍依赖 TCP,存在传输层队头阻塞(丢包重传阻塞所有流)
HTTP/3.0基于 QUIC(UDP)- 基于 UDP 的 QUIC 协议
- 多路复用(独立流,无队头阻塞)
- 头部压缩(QPACK)
- 0-RTT 快速握手
- 连接迁移(Connection ID)
- 彻底解决 TCP 队头阻塞
- 优化移动网络切换(如 IP 变化不影响连接)
- 集成 TLS 1.3 加密
- 新协议兼容性需逐步完善
- UDP 可能被部分网络设备限制

HTTP3 选择了 UDP 的原因

  • 解决了 TCP 的局限性
    • 队头阻塞
      TCP 要求数据包按序到达
      UDP 无顺序约束,QUIC 协议通过独立的流实现多路复用,单个流丢包不影响其他流。
    • 连接建立延迟
      TCP 三次握手+TLS握手
      QUIC 基于 UDP 实现 0-RTT 或 1-RTT 握手,显著降低延迟
    • 协议僵化
      TCP 协议栈内置操作系统内核,升级困难
      QUIC 在用户空间实现
  • UDP 的灵活性以及 QUIC 的增强
    • 可靠性增强
      QUIC 通过 包编号、ACK 帧、快速重传,避免了 TCP 的重传模糊。
    • 连接迁移
      TCP 连接依赖四元组(IP+端口),网络切换要重连
      QUIC 用 64 位连接 ID,IP 变化时仍可保持连接
    • 内置加密
      QUIC 默认集成 TLS 1.3
  • 适应现代网络需求
    • 移动互联网以及弱网环境
    • 多路复用与流优先级
    • 绕过中间设备限制
      新型传输协议常被防火墙拦截,UDP 广泛兼容,成本低

计算机操作系统

计算机操作系统知识总结

JS

CSS

  • 盒模型
  • 弹性盒子
  • 垂直居中
  • 选择器(类型、权重)

前端工程化

前端工程化是指将软件工程的技术和方法应用于前端开发,通过规范化、标准化和自动化的手段,提高开发效率、保障代码质量并降低维护成本。
核心目标是解决四大问题:

  • 开发效率
  • 协作规范
  • 性能优化
  • 质量保障

四大核心支柱:

  • 模块化
    JS 模块化
    CommonJS、AMD、CMD、ESM 等规范,解决全局变量污染、依赖管理问题
    CSS 模块化
    Sass/Less/Stylus 等预处理器,以及 CSS Module、CSS-in-JS
    资源模块化
    Webpack等工具将图片、字体也视为模块
  • 组件化
  • 规范化
    代码规范
    目录结构
    工作流程
    文档规范
  • 自动化
    构建工具 开发辅助

面试()

多次

  • JavaScript 类型判断
  • 如何判断变量是数组

:key 的作用

:key 是 Vue 中的一个特殊属性,主要用于唯一标识虚拟DOM节点,帮助Vue更高效地更新和渲染DOM。它的主要作用包括:

  • 唯一标识元素身份
    在列表渲染(v-for)或动态组件切换时,通过key可以精确识别每个节点
  • 优化渲染性能
    通过key的比较,Vue可以复用已有DOM节点,减少不必要的DOM操作,将算法复杂度从O(n³)优化到O(n)
  • 保持组件状态
    防止在列表更新时组件状态(如表单输入值)被意外重置或错乱
  • 正确触发过渡动画
    在元素切换时,不同的key能确保Vue重新创建元素而非复用,从而触发过渡效果

不使用 key 的后果:

  • 性能下降(无法高效复用)
  • 状态错乱
  • 渲染异常

使用 index 作为key 的问题:
当新插入的项目不在最后(eg:在开头插入,新插入的项目的 index 为 0, 则会导致后续的 index 都发生变化),无法达到提升渲染性能的目的。

底层原理:
Vue 的虚拟 DOM diff 算法

lingyi

编写的 ts 是怎么转换成 js 的

tsc

原型链

https://segmentfault.com/a/1190000042725370

原型(prototype)

  • 对象有__proto__属性,函数有__proto__属性,数组也有__proto__属性,只要是引用类型,就有__proto__属性,指向其原型。
  • 只有函数有prototype属性,指向new操作符加调用该函数创建的对象实例的原型对象。

原型链的形成

  • person1.toString() 的查找路径为:person1 → Person.prototype → Object.prototype → null

xx

  • 跨域
  • tcp 和 udp
  • https
  • 三次握手四次挥手

tx

  • vue中的 全局状态管理 和 props之类的父子间通信 的区别
    数据被多个无关组件频繁使用时 全局
  • 正向代理与反向代理
    正向代理是客户端的代理(个人翻墙、企业内网、内容过滤);反向代理是服务器的代理(负载均衡、隐藏服务器、缓存加速)
  • pinia 和 vuex 的区别
    • vuex 只有一个全局store,pinia 可以生成多个独立 store
    • vuex 通过 mutations(同步)和 actions(异步)修改状态,结构严格但代码冗长;pinia 直接使用 action 处理同步和异步操作
  • pinia 的存储
  • cookie 和 localstorage 的区别
  • 前端工程化(webpack 打包、减小体积。。。)
  • 一句话讲一下 ts 的泛型
    是一种创建可复用组件的工具,它允许我们在定义函数、接口或类时不预先指定具体类型,而是在使用时再指定,从而增强代码的灵活性和类型安全性。

清单

模块一:前端八股文与基础内功(校招必问)

这是简历《专业技能》第一段的延伸。大厂一面必然是海量的基础拷问,必须倒背如流。

  1. JavaScript 核心执行机制

    • Event Loop(事件循环):必须能手撕宏任务(setTimeout/setInterval)与微任务(Promise.then/MutationObserver)的执行顺序。浏览器与 Node.js 事件循环的差异。
    • 闭包(Closure):闭包的产生原理(词法作用域)、应用场景(比如你在做 Token 刷新队列时用到的私有变量)、以及闭包引起的内存泄漏与排查。
    • 原型与原型链:隐式原型 __proto__ 与显式原型 prototype,如何手写继承(寄生组合式继承)。
    • Promise 规范:不仅要会用,最好能手写一个简易版的 Promise,深刻理解 resolverejectthen 的链式调用和状态不可逆。
  2. 计算机网络与 HTTP 协议

    • 状态码:200、301/302、304(协商缓存)、401(未授权,与你的刷新队列强相关)、403、500。
    • 浏览器缓存机制:强缓存(Cache-Control、Expires)与协商缓存(ETag、Last-Modified)。
    • 跨域问题:为什么会跨域(同源策略)?CORS 原理(简单请求与预检请求 OPTIONS),前端 Vite 代理(Proxy)怎么配的?
  3. 数据结构与算法

    • 重点复习:数组/字符串操作、栈与队列(你的无感刷新就是队列应用)、树的遍历(多级表单和嵌套目标的场景)、以及优先队列/最小堆(MinHeap)(如果有面试官深挖你 DailyUse 的调度机制)。

模块二:框架底座(Vue 3 & TypeScript)

这是你干活的饭碗,面试官考察的是你对 Vue3 的深度理解,而不是仅仅会背 API。

  1. Vue 3 核心原理

    • 响应式原理Proxy 配合 Reflect 是怎么劫持对象的?比起 Vue2 的 Object.defineProperty 有什么绝对优势(比如监听数组和新增属性)?
    • Composition API 的精髓:为什么要出组合式 API?(逻辑复用、解决 Mixin 命名冲突与来源不清、更好的 TS 类型推导)。
    • 组件间通信:父子通信、依赖注入(Provide/Inject)、事件总线(Event Bus)以及你常用的全局状态管理。
  2. TypeScript 高级应用

    • 泛型(Generics):在封装 Axios 的 Result Pattern 返回值时(Promise<Result<T>>),泛型是怎么起作用的?
    • 接口(Interface)与类型(Type)的区别
    • 工具类型Partial, Omit, Pick, Record 的实际使用场景。

模块三:工程化、构建与性能(拉开差距的关键)

应届生懂业务的很多,懂工程化的很少。这一块是你的加分项。

  1. Vite 与前端构建

    • 为什么 Vite 在开发环境比 Webpack 快那么多?(ESM 原生模块热更新、esbuild 预构建)。
    • 生产环境 Vite 用什么打包?(Rollup)。
  2. 代码规范与 CI/CD

    • Husky + lint-staged:在 git commit 时拦截校验代码规范的原理。
    • GitHub Actions:它的基本执行流是什么样的?(监听 push/PR 事件 -> 启动 Runner 容器 -> 执行 actions 脚本)。
  3. Astro 与静态站点生成 (SSG)

    • 什么是 SSG?与 SSR、CSR 的根本区别是什么?
    • Islands 架构(孤岛架构):Astro 是如何做到 0 JS 首屏,又能在特定区域注入交互逻辑的(Hydration 指令如 client:loadclient:visible)?

模块四:全栈思维与 Node.js

这部分对应你的个人项目 DailyUse 和 Digital Biome 中的核心 Node.js 脚本。

  1. JWT 鉴权体系(重中之重)

    • Access Token 与 Refresh Token 的双 token 机制:为什么不直接把一个 token 过期时间设为一年?Refresh Token 存在哪里最安全(HttpOnly Cookie 还是 localStorage)?
    • 无感刷新并发处理:如果有 10 个请求同时 401,你是如何用 isRefreshing 锁止队列,然后统一放行的?(这是必考的亮剑题)。
  2. Node.js 与流式处理

    • fspath 的常见操作。
    • Stream(流):为什么 AI 对话(Chatbot)要用流式响应?(Server-Sent Events / Fetch ReadableStream),它的底层网络机制是什么?
  3. 数据库与 ORM (Prisma)

    • 关系型数据库基本的 JOIN 查询、联合索引。
    • 什么是 Repository(仓储)模式?(隔离业务层与数据层,如果把 Prisma 换成 Sequelize,业务代码完全不用改)。

模块五:简历项目“深水区”排雷(实战防守)

针对你的三个神级项目,必须准备好以下话术:

  1. 针对 DDCC(打印模块重构)

    • Q:为什么抛弃 html2canvas
      • A:因为截图方案会导致失真模糊,且长表格在截图分页时必定会拦腰截断里面的文字,同时无法做到动态内容(如签名表)在每一页都精准重复。
    • Q:讲讲 vue-print-next 配合 pagedjs 的原理。
      • A:vue-print-next 提取需要打印的 DOM 放进隐藏的 iframe 里;但原生浏览器的 CSS 分页兼容性极差,所以引入 pagedjs 拦截排版。它会读取 CSS 的 @page 规范,在 JS 运行时生成一个个带边界的 .pagedjs_page 虚拟物理页,并在每页底部 fixed 定位我的签名表。
  2. 针对 OLP(跨页状态丢失问题)

    • Q:你是怎么解决表格翻页,上一页勾选状态丢失的?
      • A:这是因为 Element Plus 表格的数据源在翻页时被替换了。我脱离了组件库,自己在外部维护了全局选中的 ID 数组。每次翻页拿到新数据后,用 isSettingSelection 布尔锁来暂停监听原生事件,手动将之前选中的行数据回填(toggleRowSelection),完美解决死循环和状态重置。
  3. 针对 Digital Biome(数据清洗与同步)

    • Q:你用 Node.js 同步脚本做了什么清洗?
      • A:我用正则把 Obsidian 独有的 Wikilink(如 [[页面]])转换成了标准的 Markdown 链接 [页面](url);同时读取文档的 YAML frontmatter 提取目标站点的网址,利用第三方 Favicon 接口下载图标并缓存到本地 /public,让首页不需要发几百个网络请求,提升了前端渲染速度。

100个QA

为了让你在接下来的校招和面试中拥有绝对的统治力,我为你精心准备了 100 道高频、高质量的面试 QA(问答)

这 100 题严格基于你的简历技术栈(Vue 3、TS、Node.js、工程化、网络、全栈项目实战)划分。建议你每天过 20 题,把它当做你的终极面试复习宝典。


第一部分:JavaScript & TypeScript 内功篇 (1-20)

1. let、const 和 var 的区别?

答: var 存在变量提升且没有块级作用域;let 和 const 有块级作用域,存在暂时性死区;const 声明必须赋值且引用的内存地址不可变。

2. 箭头函数和普通函数的区别?

答: 箭头函数没有自己的 this,它的 this 继承自外层词法作用域;不能作为构造函数;没有 arguments 对象。

3. 什么是闭包?有什么优缺点?

答: 闭包是指有权访问另一个函数作用域中变量的函数。优点是能实现数据私有化(如封装拦截器变量);缺点是使用不当会导致变量无法被垃圾回收,造成内存泄漏。

4. 谈谈你对原型和原型链的理解?

答: 每个对象都有 __proto__ 属性指向它的构造函数的 prototype。当访问对象属性时,如果自身没有,就会顺着 __proto__ 一直向上查找,这就构成了原型链,终点是 null

5. new 操作符究竟做了什么?

答: 创建一个空对象;将空对象的 __proto__ 指向构造函数的 prototype;将构造函数的 this 指向这个新对象并执行;返回新对象。

6. Promise 有几种状态?

答: 三种:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)。状态一旦改变就不可逆转。

7. Promise.allPromise.race 的区别?

答: all 等待所有 Promise 成功才成功,一个失败就直接失败;race 是哪个 Promise 最先出结果(不论成功失败),就返回哪个结果。

8. async/await 的原理是什么?

答: 它是 Generator 函数的语法糖,内置了执行器。把异步代码以同步的方式书写,await 后面跟着一个 Promise,会交出执行权,等 Promise 决议后再恢复执行。

9. Event Loop(事件循环)中宏任务与微任务的区别?

答: 宏任务(setTimeout/setInterval)由宿主环境发起,微任务(Promise.then/MutationObserver)由 JS 引擎发起。当前执行栈空了后,会先清空所有微任务,再执行下一个宏任务。

10. 防抖(Debounce)和节流(Throttle)的区别?

答: 防抖是“n秒内只执行最后一次”(如搜索框);节流是“n秒内无论触发多少次,只执行一次”(如滚动事件)。

11. 深拷贝和浅拷贝的区别?如何实现深拷贝?

答: 浅拷贝只拷贝一层引用;深拷贝拷贝彻底,新旧对象互不影响。实现方式有:JSON.parse(JSON.stringify(obj))(有缺陷),或手写递归函数。

12. Map 和 WeakMap 的区别?

答: WeakMap 的键只能是对象,且是弱引用,只要外部对象被销毁,WeakMap 中的键值对也会被垃圾回收器清除,适合做 DOM 节点的元数据存储。

13. TS 中 type 和 interface 的区别?

答: interface 主要用于定义对象结构,支持声明合并;type 是类型别名,可以定义基础类型、联合类型、元组等。

14. TS 中的泛型(Generics)是什么?

答: 泛型是指在定义函数、接口或类时不预先指定具体的类型,而在使用的时候再指定类型的特性。相当于类型的“参数”。

15. any 与 unknown 的区别?

答: any 完全放弃类型检查;unknown 是安全的 any,在对 unknown 类型进行操作前,必须进行类型收窄(断言或判断)。

16. 说几个 TS 常用的工具类型?

答: Partial<T>(属性全变可选)、Pick<T, K>(挑出指定属性)、Omit<T, K>(剔除指定属性)、Record<K, T>(构造对象类型)。

17. typeof 与 instanceof 的区别?

答: typeof 返回数据类型的字符串(对 null 会返回 object);instanceof 用于检查构造函数的 prototype 是否出现在某实例对象的原型链上。

18. 数组去重有哪些方法?

答: 最简单的是 […new Set(arr)];或者使用 filter 配合 indexOf;复杂对象数组需用到 reduceMap

19. call、apply、bind 的区别?

答: 都是改变 this 指向。call 传散列参数并立即执行;apply 传数组参数并立即执行;bind 传散列参数,不立即执行,而是返回一个新函数。

20. JS 垃圾回收机制?

答: 主要采用“标记清除”法(标记所有内存中可达的对象,清除不可达的)。V8 引擎采用分代回收(新生代用 Scavenge 算法,老生代用标记清除和标记压缩)。


第二部分:Vue 3 与 前端框架篇 (21-40)

21. Vue 3 相比 Vue 2 最大的优势是什么?

答: 引入了 Composition API(更好组织逻辑)、基于 Proxy 重写了响应式(解决了属性添加/删除无法监听的问题)、更好的 TS 支持、按需编译使打包体积更小。

22. refreactive 的区别?

答: ref 可定义基本数据类型和引用类型,底层用 getter/setter,访问需加 .valuereactive 只能定义对象/数组,底层用 Proxy,不能直接解构(会失去响应式)。

23. 说一下 Vue 3 的响应式原理?

答: 核心是 Proxy 配合 Reflect。通过 Proxy 拦截对象的读取(收集依赖 track)和修改(触发更新 trigger)。

24. watchwatchEffect 的区别?

答: watch 需要显式指定监听源,可拿到新旧值,默认惰性执行;watchEffect 自动收集内部依赖的变量,一上来就会立即执行一次。

25. <script setup> 语法糖有什么好处?

答: 代码更简洁,不用写 return,引入的组件直接可用,定义的方法和变量在模板中直接可用,更好的 TS 类型推导。

26. Vue 3 有哪些生命周期钩子?

答: onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted。弃用了 Vue2 的 created 系列,直接在 setup 顶层写即可。

27. Vue 3 组件间通信有哪些方式?

答: Props/Emits、Provide/Inject、Pinia 状态管理、模板引用(ref)、插槽(Slot)。

28. Pinia 相比 Vuex 的优势?

答: 移除了 mutations(直接在 actions 中操作),天然支持 TS 类型推导,体积更轻量,没有嵌套的 modules(每个 store 都是独立的)。

29. v-model 在 Vue 3 中有什么变化?

答: 默认绑定的属性名从 value 变成了 modelValue,事件名从 input 变成了 update:modelValue,且支持在一个组件上绑定多个 v-model。

30. keep-alive 的作用?会触发什么生命周期?

答: 用于缓存组件,避免频繁销毁重建。被包含的组件会触发特有的 onActivated(激活时)和 onDeactivated(失活时)生命周期。

31. Teleport 的作用是什么?

答: 可以将组件的 DOM 节点传送到页面的指定位置(如 body 下),非常适合用来做全屏的 Modal 弹窗,避免受到父组件 CSS 的 z-indexoverflow 影响。

32. nextTick 的原理和作用?

答: Vue 的 DOM 更新是异步的,nextTick 会在 DOM 更新循环结束之后执行延迟回调。原理是利用 Promise 或 MutationObserver 将回调推入微任务队列。

33. 什么是虚拟 DOM(Virtual DOM)?

答: 用 JS 对象来描述真实的 DOM 结构。改变数据时先生成新的 VNode,与旧 VNode 对比(Diff),然后把差异打在真实 DOM 上,减少直接操作真实 DOM 带来的性能开销。

34. 简单讲讲 Vue 的 Diff 算法?

答: 采用同层比较,深度优先。Vue3 引入了静态提升和靶向更新(PatchFlag),只对比带有动态标记的节点,并通过最长递增子序列算法优化了节点的移动效率。

35. 什么是自定义 Hook(Composable)?

答: 利用 Vue3 的组合式 API,将与状态相关的业务逻辑提取到一个纯函数中(一般以 use 开头),实现逻辑的复用,比 Mixin 更清晰。

36. computed 的缓存机制是什么?

答: computed 是基于其响应式依赖进行缓存的。只有当依赖的数据发生改变时,它才会重新计算,否则多次访问直接返回之前的缓存结果。

37. v-if 和 v-show 的区别?

答: v-if 是真正的条件渲染,会进行 DOM 的销毁和重建;v-show 只是简单切换 CSS 的 display 属性。频繁切换用 v-show。

38. 前端路由的 hash 和 history 模式原理?

答: hash 模式通过监听 hashchange 事件实现,URL 带 #;history 模式基于 HTML5 的 pushStatereplaceState,不带 #,但需要 Nginx 配置重定向防止 404。

39. Vue Router 有哪些导航守卫?

答: 全局守卫(beforeEach, afterEach)、路由独享守卫(beforeEnter)、组件内守卫(beforeRouteEnter, beforeRouteLeave)。

40. React Hooks 与 Vue Composition API 的区别?

答: React Hooks 每次渲染都会重新执行整个函数,严重依赖依赖数组(deps);Vue 组合式 API 的 setup 只执行一次,状态响应式更新,不用关心闭包陷阱。


第三部分:计算机网络与浏览器原理篇 (41-55)

41. 详细说说 TCP 三次握手?

答: 第一次客户端发送 SYN 报文;第二次服务端返回 SYN+ACK 报文;第三次客户端发送 ACK 报文,连接建立。(作用是确认双方的接收与发送能力正常)。

42. TCP 挥手为什么是四次?

答: 因为 TCP 是全双工的。服务端收到客户端的 FIN(我要关了)后,可以先回 ACK(知道了),但可能还有数据没发完,等发完后再发 FIN 给客户端,所以多了一次。

43. HTTP/1.1 与 HTTP/2 的区别?

答: HTTP/2 引入了多路复用(解决队头阻塞)、二进制分帧、头部压缩(HPACK)、以及服务器推送。

44. HTTPS 工作原理?

答: HTTPS = HTTP + SSL/TLS。结合了非对称加密(交换密钥)和对称加密(实际数据传输),并通过数字证书确保服务器身份的合法性。

45. 常见的 HTTP 状态码有哪些?

答: 200(成功), 301(永久重定向), 302(临时重定向), 304(使用缓存), 400(客户端请求错误), 401(未授权/Token失效), 403(禁止访问), 404(未找到), 500(服务器内部错误)。

46. GET 和 POST 的区别?

答: GET 参数在 URL 中,有长度限制,常用于获取数据,幂等;POST 参数在 Request Body 中,无限制,常用于提交数据,非幂等。

47. 什么是跨域?如何解决?

答: 浏览器的同源策略限制了协议、域名或端口不一致的请求。解决:后端配置 CORS(设置 Access-Control-Allow-Origin),或前端开发环境配置代理(Proxy)。

48. 强缓存与协商缓存的判断流程?

答: 浏览器先看强缓存(Cache-Control/Expires),没过期直接用;如果过期了,带上 ETag 或 Last-Modified 发给服务器协商,服务器如果认为没变就返回 304,否则返回 200 和新数据。

49. Cookie、sessionStorage、localStorage 的区别?

答: Cookie 会被带在每次请求头中,容量约4K;localStorage 永久存储,容量5M+;sessionStorage 关闭标签页即失效。

50. Token 存在哪里最安全?

答: 存在 localStorage 容易受 XSS 攻击被窃取;存在 HttpOnly Cookie 中不能被 JS 读取,能防止 XSS,但需防范 CSRF(通常结合 CSRF Token 解决)。

51. 从输入 URL 到页面渲染的过程?

答: DNS解析 -> TCP三次握手 -> 发送HTTP请求 -> 服务器响应 -> 浏览器解析 HTML 构建 DOM 树,解析 CSS 构建 CSSOM 树 -> 两者合成渲染树 -> 布局(Layout) -> 绘制(Paint)。

52. 重绘 (Repaint) 与回流 (Reflow) 的区别?

答: 回流是指元素的大小、位置发生改变,浏览器重新计算布局;重绘是指元素外观(如颜色)改变,不影响布局。回流必引起重绘,重绘不一定引起回流。

53. 前端如何优化首屏白屏时间?

答: 路由懒加载、图片懒加载、CDN 分发静态资源、开启 Gzip 压缩、使用骨架屏(你在简历里提到了)、提取公共库等。

54. 什么是 XSS 攻击?怎么防御?

答: 跨站脚本攻击,黑客在页面注入恶意脚本。防御:永远不要相信用户输入,进行字符转义(Escape),开启 CSP 内容安全策略,Cookie 设置 HttpOnly。

55. 什么是 CSRF 攻击?怎么防御?

答: 跨站请求伪造,利用用户已登录的身份在钓鱼网站发请求。防御:验证 Referer 字段,请求时附带不可伪造的 CSRF Token,设置 Cookie 的 SameSite 属性。


第四部分:全栈、Node.js 与业务基建篇 (56-70)

56. Node.js 的事件循环与浏览器的区别?

答: Node.js 的事件循环分为多个阶段(Timers, IO callbacks, Idle, Poll, Check, Close),而浏览器主要是一轮一轮的宏任务微任务交替。

57. CJS (CommonJS) 和 ESM 的区别?

答: CJS 是同步加载,输出的是值的拷贝(require / module.exports);ESM 是编译时输出接口,输出的是值的引用(import / export),支持 Tree Shaking。

58. Node.js 中的 Stream(流)有什么好处?

答: 流可以分片处理大文件,避免将整个文件加载到内存导致内存溢出。你在大模型(AI Chatbot)应用中用流式接收,可以实现打字机效果。

59. RESTful API 的核心设计原则是什么?

答: URL 只表示资源(名词),不用动词;使用 HTTP 动词表示操作(GET 查, POST 增, PUT/PATCH 改, DELETE 删);无状态通信。

60. JWT 的构成是什么?

答: 分为 Header(头部)、Payload(载荷/数据)、Signature(签名)。签名由 Header、Payload 加上服务器秘钥(Secret)通过算法生成,防篡改。

61. 为什么全栈项目需要 Refresh Token?

答: Access Token 泄露风险大,所以过期时间短;Refresh Token 专门用来静默刷新 Access Token,提升安全性同时保证用户体验。

62. (简历重点) 你是如何处理无感刷新 Token 的并发请求的?

答: 利用 isRefreshing 变量做锁,第一个 401 请求发起刷新并上锁;后续 401 请求将自身的 resolve 放入队列;刷新成功后,遍历执行队列重新发请求。

63. 什么是仓储模式(Repository Pattern)?

答: 介于业务逻辑层和数据访问层之间。它将数据库查询(如 Prisma 操作)封装起来,业务层只调用仓储层的方法。好处是解耦,未来更换数据库引擎不影响业务逻辑。

64. Prisma 相比传统 ORM 有什么优势?

答: 强类型支持极佳,提供 Prisma Studio,Schema 定义清晰(一个 prisma 文件即可定义数据表、外键及级联关系)。

65. 数据库的左连接 (LEFT JOIN) 和内连接 (INNER JOIN) 区别?

答: 内连接只返回两表匹配的行;左连接返回左表的所有行,如果右表没匹配上则显示 NULL。

66. 什么是数据库的联合索引?

答: 在数据库的两列或多列上建立的索引。遵循“最左前缀原则”,可以极大地优化多条件复合查询的效率。

67. 数据库事务的 ACID 特性是指什么?

答: Atomicity(原子性,同生共死)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)。

68. WebSocket 与 HTTP 的区别?

答: HTTP 是无状态、单向(客户端发)的;WebSocket 握手后建立持久的 TCP 连接,是全双工通信,服务端可主动推数据。

69. SSE (Server-Sent Events) 是什么?

答: 基于 HTTP 的单向通信机制,服务器向客户端单向推送事件数据(MIME 类型为 text/event-stream),是做 AI 流式对话的最佳方案。

70. 什么是 BFF(Backend For Frontend)层?

答: 服务于前端的后端层(一般用 Node.js 写)。用于聚合微服务的接口、清洗数据、裁剪字段,让前端拿到刚好适合渲染的数据格式。


第五部分:工程化、Vite 与部署 DevOps 篇 (71-85)

71. Vite 为什么比 Webpack 启动快?

答: Webpack 启动时需要把所有模块打包成一个 Bundle;Vite 依赖浏览器原生 ES Modules,按需编译当前路由所需的模块,启动近乎零耗时。

72. Vite 的依赖预构建机制是什么?

答: 首次启动时,Vite 会用 esbuild 把项目里的 CommonJS/UMD 依赖转换为 ESM 并缓存,解决了第三方包不支持 ESM 和请求过多的问题。

73. Webpack 和 Rollup 的核心定位区别?

答: Webpack 适合打包庞大的业务应用,支持代码分割和静态资源处理;Rollup 打包产物更纯粹,极其适合打包第三方 JS 库或组件库。

74. Husky 和 lint-staged 是干什么用的?

答: Husky 用于劫持 Git Hooks(如 pre-commit);lint-staged 配合 Husky,只对暂存区(Git Add)的代码运行 ESLint/Prettier,保障提交规范。

75. ESLint 和 Prettier 的分工?

答: ESLint 负责检查“代码质量”(如不用 var、未使用的变量);Prettier 只负责“代码格式化”(如缩进、单双引号)。

76. 什么是 CI/CD?

答: 持续集成(Continuous Integration)和持续交付/部署(Continuous Deployment)。代码推送后自动触发测试、构建和部署,取代人工操作。

77. 简述 GitHub Actions 的基本概念?

答: 它是一个自动化流工具。包含 Workflow(工作流配置文件 yml)、Event(触发事件如 push/pr)、Job(任务)和 Step(具体执行的命令)。

78. 前端项目如何实现多环境隔离?

答: 建立 .env.development.env.production 等文件。在 Vite 中通过 import.meta.env 注入变量,打包时根据指定的 mode 读取不同配置。

79. SSR、SSG、CSR 的区别?

答: CSR 客户端渲染(全靠 JS 绘图,首屏慢);SSR 服务端渲染(每次请求都在 Node 侧生成 HTML,利于 SEO);SSG 静态站点生成(构建阶段直接生成好所有静态 HTML)。

80. Astro 框架在前端生态中的核心优势是什么?

答: 它天生支持内容驱动的静态网站构建。主打“0 JS”首屏加载(将 JS 剥离),且支持混合使用 React/Vue/Svelte 组件。

81. 什么是 Islands(孤岛)架构?

答: 大面积页面是纯静态 HTML,只有需要交互的部分(如深色模式开关、评论区)才像“孤岛”一样加载 JS 水合(Hydration)。极大提升了页面性能。

82. 简述 Docker 镜像和容器的关系?

答: 镜像(Image)是静态的只读模板(类似于类);容器(Container)是镜像的运行实例(类似于对象),容器内带有完整的运行环境。

83. 为什么要写 Docker 多阶段构建(Multi-stage Build)?

答: 第一阶段包含打包环境(如 Node+pnpm 打包出 dist),第二阶段只用极简的 Nginx 镜像并拷贝 dist。这样最终镜像不包含源码和依赖,体积小且安全。

84. 什么是正向代理与反向代理?

答: 正向代理代理客户端(如翻墙梯子,服务器不知道真正的客户端);反向代理代理服务端(如 Nginx 负载均衡,客户端不知道请求的具体是哪台机器)。

85. Vue 单页应用部署在 Nginx 时,为什么刷新会 404?怎么解决?

答: 因为只有一个 index.html,路径都是前端虚拟路由,服务端找不到真实文件。解决:Nginx 配置 try_files $uri $uri/ /index.html;,将 404 定向回入口文件。


第六部分:你的简历实战深水区 (86-100)

86. (DDCC项目) 为什么重构打印模块时,要抛弃 html2canvas?

答: 截图方案会导致文字发虚;面对长表格分页时会从字中间“拦腰截断”;并且无法优雅地实现在每一页都重复渲染相同的页脚(签名表)。

87. (DDCC项目) pagedjs 的核心原理是什么?

答: 原生 CSS 的打印分页各浏览器兼容性极差。pagedjs 充当了 Polyfill,它读取 CSS @page 规范,在 JS 内存中进行数学计算,动态生成一个个物理尺寸的隔离容器进行精准排版。

88. (DDCC项目) 如何实现动态签名表在打印的每页底部固定重复?

答: 利用 @media print 媒体查询,给签名表加上 position: fixed; bottom: 0;,浏览器打印引擎会在每一张纸上都渲染这个 fixed 元素。

89. (OLP项目) 你的 AI 知识生成模块,是如何接收流式数据的?

答: 调用 fetch 后拿到 Response.body,它是一个 ReadableStream。通过 getReader() 逐步读取 Chunk 数据,再用 TextDecoder 解码拼接到视图变量上,实现打字机效果。

90. (OLP项目) 后台管理系统的分页表格,跨页选中状态丢失的原因是什么?

答: 大部分 UI 组件库的表格默认只维护当前页的数据源。一旦请求下一页接口,数据源被替换,之前的选中状态引用就会被清理。

91. (OLP项目) 解决状态丢失时,为什么要设计一个 isSettingSelection 的布尔值锁机制?

答: 当我们跨页回来,用代码手动触发表格的“勾选(回填)”方法时,会意外触发组件库原生的 selection-change 事件,导致我们自己维护的全局数组被错误清空。加锁可以避开原生事件的死循环干扰。

92. (Biome项目) Astro 项目配合 Pagefind 是怎么实现极速纯静态搜索的?

答: 它不需要后端数据库。在 Astro 构建输出静态文件(dist)后,Pagefind 读取这些 HTML,预先建立索引分块。前端搜索时直接请求极小的分块文件实现毫秒级响应。

93. (Biome项目) 你的 Node.js 脚本是怎么解析 Markdown 中的 Obsidian 双链的?

答: 引入 Node 的 fs 模块读取文本,编写正则表达式 匹配 \[\[(.*?)\]\],利用 replace 方法将内部的链接名提取出来,重写为标准的 Markdown [name](name) 格式。

94. (Biome项目) 为什么要把获取 Favicon 这样的操作写在 Node.js 同步脚本里,而不是前端去发请求?

答: 如果前端在导航页向第三方接口发几百个获取图标的请求,会严重阻塞渲染且触发接口限流。在 Node 层构建时清洗并缓存到本地,前端直接读同源静态文件,性能实现了质的飞跃。

95. (DailyUse全栈) 你封装 Axios 时的 Result Pattern(结果模式)解决了什么业务痛点?

答: 传统写法,任何 400/500 的 HTTP 错误都会抛出异常,前端必须写无数个冗余的 try-catch,一旦漏写就会白屏。我拦截所有异常,统一包装为 { ok: false, error },让业务逻辑如丝般顺滑。

96. (DailyUse全栈) 面对巨型表单,你是怎么做组件拆解的?

答: 我打破了单一文件的写法,按照“基础信息”、“时间配置”、“高级规则”切分成多个独立的业务组件。子组件绝不直接修改 props 数据,而是统一 emit 事件向上流转。

97. (DailyUse全栈) 既然拆散了组件,你是怎么解决“父组件怎么知道表单全填对了”这个验证难题的?

答: 我提取了一个专属的自定义 Hook。里面管理着各个子模块的验证状态变量,最终暴露出一个汇总的 computed 属性 isFormValid。实现了验证逻辑的聚合与视图的解耦。

98. (DailyUse后端) 在 Prisma 建表时,你提到了 Cascade(级联),这是解决什么问题的?

答: 比如任务表和评论表是一对多,如果在 Schema 中配置了外键的 onDelete: Cascade,当我在数据库删除这条任务时,底层会自动删除所有与之关联的评论,防止产生垃圾孤儿数据。

99. (DailyUse实战) 什么是单向数据流?它在你的全栈项目中有什么体现?

答: 数据只能从父组件流向子组件,子组件不能直接修改父组件传来的数据。在我的拆分组件中体现为:数据属于父级,子级只负责“展示”和“通知父级去改”,保证了数据变更追踪的可控性。

100. (综合送分题) 你觉得在公司实习(如 OLP/DDCC)和你自己搞独立开源项目(DailyUse/Biome),最大的区别是什么?

答: 实习让我学会了在既定框架内工作、遵守 Git 分支流和企业级代码规范,懂得了业务妥协和跨部门沟通;而自己做全栈项目则逼迫我站在”架构师”的视角从 0 思考选型、数据库设计和 CI/CD 闭环,两者结合让我既具备大局观,又拥有极强的落地执行力。

📖 相关资源

AI 工程师面试复盘

核心教训

AI 工程师面试最吃亏的不是”没做过”,而是”说不清工程细节”。面试官会逐层追问,验证你是否真的能独立落地。

最常见的扣分模式

  1. 说到关键词就停:说了”状态机""Schema 校验""重试”,但没继续讲状态有哪些、数据结构怎么设计、重试条件是什么
  2. 回答停留在概念层:面试官问实现细节,回答”可以用现成库""让 AI 帮我规划”
  3. TypeScript 类型能力偏弱as type 断言不是类型安全,泛型 + 条件类型才是正解

每个回答应该覆盖的层次

状态有哪些?数据结构怎么设计?失败怎么处理?重试条件是什么?怎么防止重复执行?代码层面用什么库?怎么观测效果?

关键知识点速查

主题新笔记
Function Calling 参数校验function-calling-parameter-validation-and-retry
SSE 流式暂停与中断sse-streaming-pause-and-cancel
多模型 Provider 抽象multi-model-llm-provider-abstraction
首字延迟全链路优化ai-assistant-first-token-latency-optimization
Token 成本优化llm-token-cost-optimization-strategies
TypeScript 高级类型typescript-advanced-types

自我介绍模板

我是 XX 专业 XX 届毕业生,主要技术栈是 TypeScript、Node.js、React/Vue,前后端都有项目经验。最近比较核心的项目是 XX,我主要负责从产品方案、前后端开发、AI 能力接入、测试、CI/CD 到云服务器部署的完整链路。

项目表达结构(STAR)

  • Situation:背景是什么
  • Task:我负责什么
  • Action:技术难点是什么,我怎么解决
  • Result:最终效果是什么,如果重构会怎么做
创建于 2025/1/1 更新于 2026/5/27