Skip to Content
Nextra 4.0 is released 🎉
企业真题xxx游-前端开发工程师

xxx游-前端开发工程师

说一说操作系统中线程和进程的定义和区别?为什么一个进程要分出多个线程?

定义:

特性进程线程
定义程序的一次执行实例进程内的执行单位
资源拥有独立的内存空间共享进程的内存空间
创建开销
通信进程间通信困难线程间通信简单
同步进程独立需要同步机制

为什么使用多线程:

  1. 提高响应性 - UI 线程不阻塞
  2. 充分利用多核 - 并发执行
  3. 资源共享 - 内存空间共享,通信高效
  4. 简化编程 - 相比多进程

你了解哪些排序算法

  1. 冒泡排序 - O(n²)
  2. 快速排序 - O(n log n)
  3. 合并排序 - O(n log n)
  4. 插入排序 - O(n²)
  5. 选择排序 - O(n²)
  6. 堆排序 - O(n log n)
  7. 计数排序 - O(n+k)

口喷快速排序步骤?基准值一般取哪个值?

快速排序步骤:

  1. 选择基准值(Pivot)
  2. 分区:小于基准放左边,大于基准放右边
  3. 递归排序左右两个子数组

代码实现:

function quickSort(arr) { if (arr.length <= 1) return arr; const pivot = arr[Math.floor(arr.length / 2)]; const left = arr.filter(x => x < pivot); const middle = arr.filter(x => x === pivot); const right = arr.filter(x => x > pivot); return [...quickSort(left), ...middle, ...quickSort(right)]; }

基准值选择:

  • 第一个元素 - 简单但可能退化
  • 最后一个元素 - 简单但可能退化
  • 中间值(推荐)- 平衡性好
  • 随机选择 - 避免最坏情况

什么是单链表?什么是循环链表?

单链表: 每个节点有数据和指向下一个节点的指针

头 → 节点1 → 节点2 → 节点3 → null

循环链表: 最后一个节点指向第一个节点(形成环)

头 → 节点1 → 节点2 → 节点3 → 头(循环)

单链表实现:

class Node { constructor(data) { this.data = data; this.next = null; } } class LinkedList { constructor() { this.head = null; } append(data) { const newNode = new Node(data); if (!this.head) { this.head = newNode; } else { let current = this.head; while (current.next) { current = current.next; } current.next = newNode; } } }

手撕单链表和循环链表?

单链表完整实现:

class SinglyLinkedList { constructor() { this.head = null; this.size = 0; } append(data) { const node = new Node(data); if (!this.head) { this.head = node; } else { let current = this.head; while (current.next) current = current.next; current.next = node; } this.size++; } insert(data, index) { if (index < 0 || index > this.size) return false; const node = new Node(data); if (index === 0) { node.next = this.head; this.head = node; } else { let current = this.head; let previous; let count = 0; while (count < index) { previous = current; current = current.next; count++; } node.next = current; previous.next = node; } this.size++; return true; } remove(index) { if (index < 0 || index >= this.size) return null; let current = this.head; if (index === 0) { this.head = current.next; } else { let previous; let count = 0; while (count < index) { previous = current; current = current.next; count++; } previous.next = current.next; } this.size--; return current.data; } } class Node { constructor(data) { this.data = data; this.next = null; } }

循环链表实现:

class CircularLinkedList extends SinglyLinkedList { append(data) { const node = new Node(data); if (!this.head) { this.head = node; node.next = this.head; // 关键:指向自己 } else { let current = this.head; while (current.next !== this.head) { // 循环条件改变 current = current.next; } current.next = node; node.next = this.head; // 新节点指向头 } this.size++; } }

说一说get和post有什么区别?

特性GETPOST
用途获取资源提交数据
参数位置URL 查询字符串请求体
安全性低(可见)较高(隐藏)
缓存默认缓存不缓存
数据长度限制(URL 长度)无限制
编码URL 编码多种编码方式
幂等性幂等非幂等

使用示例:

// GET fetch('/api/users?page=1&limit=10'); // POST fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John' }) });

讲一讲 osi 七层协议

名称功能协议
7应用层应用程序、网络服务HTTP、HTTPS、FTP、SMTP
6表示层数据加密、格式转换SSL/TLS、JPEG、GIF
5会话层建立、维护、结束会话HTTP、HTTPS
4传输层端到端通信、流量控制TCP、UDP
3网络层路由、IP 寻址IP、ICMP、IGP
2数据链路层MAC 寻址、物理传输PPP、以太网
1物理层物理设备、信号传输电压、光纤

TCP 和 HTTP 分别在哪一层

  • TCP - 传输层(第 4 层)
  • HTTP - 应用层(第 7 层),基于 TCP

TCP 和 UDP 的区别

特性TCPUDP
连接面向连接无连接
可靠性可靠不可靠
速度
开销
用途文件传输、邮件、HTTP音视频、DNS、游戏
顺序保证顺序不保证顺序

TCP 怎么保证稳定的连接?说一说三次握手四次挥手过程?

三次握手(建立连接):

客户端 服务器 | | |-- SYN --> | (1) 客户端发送 SYN | | | <-- SYN-ACK --| (2) 服务器回复 SYN-ACK | | |-- ACK --> | (3) 客户端发送 ACK | | | 连接已建立 |

四次挥手(关闭连接):

客户端 服务器 | | |-- FIN --> | (1) 客户端发送 FIN | | | <-- ACK --| (2) 服务器回复 ACK | | | <-- FIN --| (3) 服务器发送 FIN | | |-- ACK --> | (4) 客户端发送 ACK | | | 连接已关闭 |

为什么 TCP 可靠:

  1. 三次握手建立可靠连接
  2. 序列号标记每个字节
  3. 校验和验证数据完整性
  4. 重传机制处理丢失的包
  5. 流量控制和防拥塞

一个请求由哪些部分构成

HTTP 请求:

请求行 GET /api/users HTTP/1.1 请求头 Host: example.com User-Agent: Mozilla/5.0 Content-Type: application/json Authorization: Bearer token 空行 请求体(可选) { "name": "John" }

HTTP 响应:

状态行 HTTP/1.1 200 OK 响应头 Content-Type: application/json Content-Length: 100 Set-Cookie: xxx=yyy 空行 响应体 { "id": 1, "name": "John" }

说一说常见的请求头的字段

请求头说明
Accept客户端接受的内容类型
Accept-Encoding接受的编码方式(gzip、deflate)
Accept-Language接受的语言
Authorization身份认证凭证
Cache-Control缓存策略
Content-Type请求体的内容类型
Content-Length请求体的长度
Host目标服务器地址
Referer来源页面
User-Agent客户端信息
If-Modified-Since条件请求,检查资源是否修改
If-None-Match条件请求,检查 ETag 是否匹配

讲一讲你了解的状态码

状态码说明例子
1xx信息100 Continue
2xx成功200 OK、201 Created、204 No Content
3xx重定向301 Moved、302 Found、304 Not Modified
4xx客户端错误400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found
5xx服务器错误500 Internal Server Error、502 Bad Gateway、503 Service Unavailable

说一说为什么会有跨域这个问题?怎么解决?

原因: 浏览器同源策略(协议、域名、端口相同才算同源)

解决方案:

  1. CORS - 后端设置响应头

    res.set('Access-Control-Allow-Origin', '*');
  2. 代理 - 开发环境或同源代理

  3. JSONP - 仅支持 GET

  4. PostMessage - 跨窗口通信


正向代理和反向代理的区别

特性正向代理反向代理
位置客户端侧服务器侧
作用隐藏客户端隐藏服务器
用途VPN、科学上网负载均衡、CDN
区别客户端知道代理客户端不知道代理

输入一个 url 地址到页面渲染的过程

  1. DNS 解析 - URL → IP 地址
  2. TCP 连接 - 三次握手建立连接
  3. HTTP 请求 - 浏览器发送请求
  4. 服务器响应 - 返回 HTML、CSS、JS
  5. 解析 HTML - 构建 DOM 树
  6. 加载资源 - 并行加载 CSS、JS、图片
  7. 解析 CSS - 构建 CSSOM 树
  8. 构建渲染树 - 合并 DOM 和 CSSOM
  9. 布局 - 计算元素位置和大小
  10. 绘制 - 填充像素点
  11. 合成 - GPU 加速渲染

Js 和 Css 加载会不会影响 Dom 的解析

资源影响说明
CSS不阻塞CSS 放在 head,不阻塞 DOM 解析
JS阻塞JS 执行会阻塞 DOM 解析(内联或普通加载)

优化:

<!-- JS 延迟加载,不阻塞 DOM --> <script defer src="script.js"></script> <!-- JS 异步加载 --> <script async src="script.js"></script>

原型和原型链

原型: 对象的隐式属性 __proto__,指向构造函数的 prototype

原型链: 对象通过 __proto__ 链接形成的继承链

const obj = {}; obj.__proto__ === Object.prototype; Object.prototype.__proto__ === null; // 原型链顶端

怎么通过原型链进行继承?最顶端会找到哪里?

原型链继承:

function Parent() { this.x = 1; } function Child() { this.y = 2; } Child.prototype = new Parent(); const child = new Child(); console.log(child.x); // 1(通过原型链找到)

原型链最顶端:

child.__proto__ = Child.prototype (Parent 实例) → Parent.prototype → Object.prototype → null(最顶端)

判断一个对象的属性是否为自己的属性, 不是原型链上的属性?

const obj = { x: 1 }; Object.setPrototypeOf(obj, { y: 2 }); // hasOwnProperty:仅检查自身属性 console.log(obj.hasOwnProperty('x')); // true console.log(obj.hasOwnProperty('y')); // false // in 操作符:检查自身和原型链 console.log('x' in obj); // true console.log('y' in obj); // true

let const var 的区别

特性varletconst
作用域函数作用域块级作用域块级作用域
提升提升(undefined)不提升不提升
重新声明✅ 可以❌ 不能❌ 不能
重新赋值✅ 可以✅ 可以❌ 不能
初始值可选可选必须

说一说对闭包的理解

闭包: 函数能够访问外层作用域的变量

function outer() { const x = 1; return function inner() { return x; }; } const fn = outer(); console.log(fn()); // 1

常见用途:

  1. 数据隐藏 - 私有变量
  2. 工厂函数 - 创建带状态的函数
  3. 回调函数 - 保存上下文

手撕防抖

function debounce(fn, delay) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); }; } // 使用 const search = debounce((query) => { console.log(`搜索: ${query}`); }, 500); input.addEventListener('input', (e) => { search(e.target.value); });

讲讲事件循环机制?微任务会一次性清空一个, 还是全部清除? 执行微任务的过程中又产生了微任务会什么时候执行? 什么时候会产生?

事件循环流程:

  1. 执行同步代码
  2. 微任务队列清空(全部执行)
  3. 宏任务执行一个
  4. 重复 2-3 步

微任务全部清除:

Promise.resolve() .then(() => { console.log('1'); Promise.resolve().then(() => console.log('2')); }) .then(() => { console.log('3'); }); // 输出:1 2 3 // 微任务队列不是逐个清除,而是一直执行直到清空

微任务产生时机:

  • Promise.then/catch/finally
  • async/await
  • MutationObserver
  • queueMicrotask()

有哪些写异步的方法

  1. 回调函数 - Callback
  2. Promise - then/catch
  3. async/await - 基于 Promise
  4. 生成器 - Generator(yield)
  5. 事件监听
  6. 发布订阅
  7. RxJS - Observable

用过 React 的 Hooks 吗?

常用 Hooks:

// useState:状态 const [count, setCount] = useState(0); // useEffect:副作用 useEffect(() => { // 组件挂载、更新时执行 return () => { // 清理函数 }; }, [dependencies]); // useContext:上下文 const value = useContext(MyContext); // useReducer:复杂状态管理 const [state, dispatch] = useReducer(reducer, initialState); // useMemo:记忆值 const memoValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]); // useCallback:记忆函数 const memoFn = useCallback(() => { doSomething(a, b); }, [a, b]); // useRef:保持引用 const inputRef = useRef(null);

讲讲 Promise 的 all 和 race 方法

Promise.all

Promise.all([ Promise.resolve(1), Promise.resolve(2), Promise.resolve(3) ]).then(values => { console.log(values); // [1, 2, 3] }); // 一个失败,整体失败 Promise.all([ Promise.resolve(1), Promise.reject('error') ]).catch(err => { console.log(err); // 'error' });

Promise.race

Promise.race([ Promise.resolve(1), new Promise(r => setTimeout(() => r(2), 100)) ]).then(value => { console.log(value); // 1(首个完成) });

vue 的生命周期

Vue 2:

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

Vue 3(Composition API):

  • setup(替代 beforeCreate、created)
  • onBeforeMount
  • onMounted
  • onBeforeUpdate
  • onUpdated
  • onBeforeUnmount
  • onUnmounted

Http1.1 和 Http2.0 的区别

特性HTTP/1.1HTTP/2.0
多路复用❌ 每个请求一个连接✅ 一个连接多个流
头压缩❌ 原始格式✅ HPACK 压缩
服务器推送❌ 无✅ 有
二进制分帧❌ 文本✅ 二进制
性能基准快 2-3 倍

讲讲 Https 的握手过程

客户端 服务器 | | |-- ClientHello---| (1) 发送支持的加密套件 | | |<-- ServerHello --| (2) 选择加密套件、发送证书 | | |<-- Certificate --| (3) 服务器证书 | | |<-- ServerKeyExchange --| (4) 密钥交换 | | |-- ClientKeyExchange--| (5) 客户端密钥交换 | | |-- ChangeCipherSpec--| (6) 通知改用加密 | | |-- Finished ---| (7) 握手完成 | | |<-- ChangeCipherSpec--| (8) 服务器通知 | | |<-- Finished --| (9) 服务器握手完成 | | | 加密通信开始 |

强缓存和协商缓存

特性强缓存协商缓存
是否请求❌ 不请求✅ 发请求验证
状态码200304
头设置Expires、Cache-ControlLast-Modified、ETag
性能最快一般

强缓存:

Cache-Control: max-age=3600 // 1小时内直接使用 Expires: Wed, 21 Oct 2025 07:28:00 GMT

协商缓存:

Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT ETag: "abc123" If-None-Match: "abc123"

302 是什么? 403 是什么? 401 是什么?

状态码说明
302临时重定向(Found)
403禁止访问(Forbidden)
401未授权(Unauthorized)

哪些地方需要用到缓存

  1. HTTP 缓存 - 浏览器缓存
  2. LocalStorage/SessionStorage - 客户端缓存
  3. 数据库缓存 - Redis、Memcached
  4. CDN 缓存 - 静态资源分发
  5. 浏览器内存缓存 - 计算结果
  6. 接口响应缓存 - API 结果

CPU 的调度算法

  1. FCFS - 先来先服务
  2. SJF - 最短作业优先
  3. 优先级调度 - 按优先级
  4. 时间片轮转 - 轮询
  5. 多级反馈队列 - 组合算法

链表的结构? 跟数组的区别

链表结构: 节点 = 数据 + 指针

对比:

特性数组链表
访问O(1)O(n)
插入O(n)O(1)
删除O(n)O(1)
内存连续离散
大小固定(通常)动态
Last updated on