大厂面经
这里收录了我在一线互联网大厂的面试经历与真题复盘。
🏢 北京
🏢 上海
🏢 深圳
🏢 广州/佛山
上海禾赛科技
📌 面试概览
- 核心:JS 基础深度 + 项目亮点挖掘。
- 特点:考察数组去重、图片压缩细节。
📝 核心知识点解析
1. 数组去重 (非引用类型)
场景:[1, 2, 1, 2] 去重。
- Set (最简):
[...new Set(arr)] - Filter (面试官指定):
javascript
const arr = [1, 2, 1, 2];
const unique = arr.filter((item, index) => {
// indexOf 总是返回第一个匹配项的下标
// 如果当前下标 === 第一个匹配项下标,说明是第一次出现
return arr.indexOf(item) === index;
});- Map (性能好): 利用 Map 的 Key 唯一性。
2. CORS (跨域资源共享)
- 简单请求: HEAD/GET/POST,且 Header 仅限 Accept, Accept-Language, Content-Language, Content-Type (限 text/plain, multipart/form-data, application/x-www-form-urlencoded)。
- 流程: 浏览器直接发送请求,后端返回
Access-Control-Allow-Origin。
- 流程: 浏览器直接发送请求,后端返回
- 复杂请求: 其他请求 (如 PUT/DELETE, application/json)。
- 流程: 浏览器先发 OPTIONS 预检请求 (Preflight),询问服务器是否允许。服务器通过后,再发真实请求。
3. Props 详解 (Vue)
- 属性:
type,default,required,validator(自定义验证)。 - 内容: 主要是数据 (String/Number/Object),图片通常传 URL 字符串。
4. 图片压缩细节 (项目亮点)
- 压缩前: PNG/JPEG (体积大)。
- 压缩后: WebP (体积小,支持透明)。
- 工具:
- 开发时:
image-webpack-loader/vite-plugin-imagemin. - 运行时: Canvas
toDataURL('image/jpeg', quality). - 服务侧: CDN 自动转换 (阿里云 OSS
?x-oss-process=image/format,webp).
- 开发时:
懂车帝 (北京)
📌 面试概览
- 岗位:Web3D 前端实习
- 轮次:两轮技术面 (10.30 一面, 10.31 二面)
- 特点:Web3D 图形学基础 + React 深度 + 浏览器原理 + 算法手撕
📝 核心知识点解析 (一面)
1. requestAnimationFrame (RAF)
- 原理:由浏览器决定回调频率(通常 60FPS,即 16.6ms 一次),在下一次重绘之前执行。
- 优点:自动节能(页面隐藏时停止),防止掉帧(与屏幕刷新同步)。
- 计算帧数 (FPS):
javascript
let lastTime = performance.now();
let frame = 0;
function loop() {
const now = performance.now();
frame++;
if (now - lastTime >= 1000) {
console.log('FPS:', frame);
frame = 0;
lastTime = now;
}
requestAnimationFrame(loop);
}
loop();2. React Hooks: useMemo vs useEffect
| Hook | 作用 | 执行时机 | 代码示例 |
|---|---|---|---|
| useMemo | 缓存计算结果 | 渲染期间执行 | const val = useMemo(() => compute(a), [a]) |
| useEffect | 处理副作用 (DOM, 请求) | 渲染结束后执行 | useEffect(() => { fetch() }, []) |
自定义 Hook 示例 (useWindowSize):
javascript
function useWindowSize() {
const [size, setSize] = useState({ width: window.innerWidth });
useEffect(() => {
const handleResize = () => setSize({ width: window.innerWidth });
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return size;
}3. Three.js 三大矩阵
| 矩阵 | 作用 | 变换过程 |
|---|---|---|
| 模型矩阵 (Model Matrix) | 物体 -> 世界坐标 | 本地坐标 (0,0,0) -> 放置在场景中 |
| 视图矩阵 (View Matrix) | 世界坐标 -> 相机坐标 | 根据相机位置/朝向变换物体 |
| 投影矩阵 (Projection Matrix) | 相机坐标 -> 裁剪坐标 | 3D 空间 -> 2D 屏幕 (透视/正交) |
渲染顺序: Local -> (Model) -> World -> (View) -> Camera -> (Projection) -> Clip -> Screen
4. 事件循环 (Event Loop) 笔试题
题目:输出顺序是 2 3 5 4 1。为什么?
javascript
setTimeout(() => console.log(1)); // 宏任务
new Promise(resolve => {
console.log(2); // 同步
resolve();
console.log(3); // 同步
}).then(() => console.log(4)); // 微任务
console.log(5); // 同步解析:
- 同步代码:
2,3,5依次执行。 - 微任务队列:
then回调 (4) 入队。 - 宏任务队列:
setTimeout回调 (1) 入队。 - 清空同步 -> 清空微任务 (
4) -> 执行宏任务 (1)。
5. 渲染管线:不透明 vs 透明物体
- 渲染顺序:
- 先渲染不透明物体(从前向后,利用深度缓冲 Z-Buffer 剔除被遮挡像素,优化性能)。
- 后渲染透明物体(从后向前,为了正确混合颜色)。
- 原因:透明物体需要和后面的颜色混合,如果先渲染透明的,深度写入后,后面的物体会被剔除,导致看不到透明物体背后的东西。
6. Web3D 深度问题 (补充)
- PBR (Physically Based Rendering): 基于物理的渲染。
- 核心属性:
Albedo(反照率),Metallic(金属度),Roughness(粗糙度),Normal(法线),AO(环境光遮蔽)。 - 优点: 真实感强,在不同光照下表现一致。
- 核心属性:
- SSR Pass (Screen Space Reflection): 屏幕空间反射。
- 后处理效果,利用已渲染的屏幕像素模拟反射。
- Draco 压缩:
- Google 开源的 3D 模型压缩库。
- 原理: 压缩几何体数据 (顶点位置、法线、UV)。
- 使用: 需要引入
DracoLoader和对应的 decoder wasm 文件。
7. JS 基础补充
- 深拷贝 vs 浅拷贝:
- 浅拷贝:
Object.assign,...spread(只拷贝一层引用)。 - 深拷贝:
JSON.parse(JSON.stringify)(不支持函数/Symbol),structuredClone(原生), 递归手写。
- 浅拷贝:
- forEach vs map:
forEach: 遍历数组,无返回值,会修改原数组 (如果是引用类型)。map: 返回新数组,不修改原数组。
- 闭包:
- 定义: 函数有权访问另一个函数作用域中的变量。
- 优点: 变量私有化,保持状态。
- 缺点: 内存不释放,易导致内存泄漏。
- React Key: Diff 算法的核心。用于追踪列表中元素及其状态,提升渲染性能。
8. 设计模式
- 单例模式: 全局唯一实例 (如 Vuex Store, Modal 弹窗)。
- 发布订阅模式:
on(订阅),emit(发布) (如 EventBus)。 - 观察者模式: 目标对象状态变更通知所有观察者 (如 Vue 响应式原理
Dep->Watcher)。
9. 算法手撕
无重复字符的最长子串 (滑动窗口)
javascript
function lengthOfLongestSubstring(s) {
let map = new Map();
let left = 0, maxLen = 0;
for (let i = 0; i < s.length; i++) {
if (map.has(s[i])) {
left = Math.max(left, map.get(s[i]) + 1);
}
map.set(s[i], i);
maxLen = Math.max(maxLen, i - left + 1);
}
return maxLen;
}岛屿的最大面积 (DFS)
javascript
function maxAreaOfIsland(grid) {
let max = 0;
const dfs = (r, c) => {
if (r < 0 || c < 0 || r >= grid.length || c >= grid[0].length || grid[r][c] === 0) return 0;
grid[r][c] = 0; // 沉岛,避免重复访问
return 1 + dfs(r+1, c) + dfs(r-1, c) + dfs(r, c+1) + dfs(r, c-1);
}
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] === 1) max = Math.max(max, dfs(i, j));
}
}
return max;
}10. Web3D 与图形学补充
- DPR 与图片:DPR (Device Pixel Ratio) = 物理像素 / 逻辑像素。
div宽高 30px,在 DPR=2 的屏幕上,对应物理像素 60px。- 图片应准备 @2x (60px) 或 @3x (90px) 以保证清晰度。
- GIS 按需加载:四叉树 (QuadTree) 算法。根据相机视口范围 (Frustum Culling) 和距离 (LOD),只加载可视区域内的瓦片数据。
- Zustand:轻量级状态管理。基于 Hooks,无 Provider 嵌套,API 简洁 (
create,set,get)。 - DrawCall 限制:通常移动端建议 < 100,PC 端 < 1000。过多会导致 CPU 提交命令阻塞 GPU。
- 动画方案对比:
- CSS: 简单 UI 动画,性能最好 (GPU 合成)。
- JS: 复杂逻辑动画,灵活性高,但易阻塞主线程。
- Canvas: 大量粒子/图形动画,性能高。
- CPU vs GPU:
- CPU: 核心少,适合复杂逻辑控制。
- GPU: 核心多 (数千个),适合并行计算 (像素渲染)。
📝 二面核心复盘 (综合与深挖)
1. 综合素质与 HR 问题
- 学历与成绩: 考察学习基础和聪明程度。
- 实习经历: 为什么离职?(寻找更合适的发展平台/技术挑战)。
- 团队管理: 如果作为 Leader,如何分配任务?(根据成员特长 + 代码 Review + 技术分享)。
- 未来规划: 专注于 Web3D/图形学领域,深耕前端工程化。
2. 项目深挖 (首屏优化)
- 关键指标: FCP (首屏时间), LCP (最大内容渲染)。
- 优化手段:
- 资源压缩: Gzip, WebP。
- 按需加载: 路由懒加载, 组件异步加载。
- 预加载:
preload关键资源。 - 3D 模型优化: Draco 压缩, 纹理压缩 (KTX2), LOD (多细节层次)。
3. 虚拟 DOM (Virtual DOM)
- 本质: 用 JS 对象描述 DOM 结构。
- 价值:
- 跨平台: 可以渲染到 Web, iOS, Android (React Native)。
- 性能优化: 减少真实 DOM 操作次数(通过 Diff 算法计算最小变更)。
4. ECharts 渲染模式
- Canvas (默认): 性能好,适合数据量大 (>1000),支持导出图片。
- SVG: 内存占用低,缩放不失真,适合移动端和数据量小。
5. 成就感事件 (STAR 法则)
- Situation: 项目遇到性能瓶颈 (FPS < 20)。
- Task: 需要优化渲染性能。
- Action: 引入 InstancedMesh (实例化渲染), 使用 Draco 压缩模型, 优化 Shader。
- Result: FPS 提升至 60,首屏加载时间减少 50%。
美云智数 (佛山)
📌 面试概览
- 时长:50分钟 (OC)
- 业务:美的集团旗下,工业互联网软件系统。
- 重点:开源项目经历、实习经历、项目流程。
📝 经验复盘
- 开源优势:面试官非常看重开源贡献(如腾讯开源项目、自研 MD 预览器),体现技术热情和底层能力。
- AI 时代前端发展:
- 低代码/零代码:前端需更多关注架构设计和组件封装。
- AI 辅助:利用 Copilot 等工具提升效率,从“写代码”转向“审代码”和“设计逻辑”。
- 项目流程:
- 售前 -> 产品/UI设计 -> 开发 -> 测试 -> 运维 -> 交付。
- 前端需参与需求评审,评估技术可行性。
盛趣游戏 (上海)
📌 面试概览
- 时长:45分钟(30分钟八股)
- 核心环节:自我介绍 + 八股文提问(12个重点方向) + 项目亮点 + 反问
📝 八股文知识点详解
1. Vue 2 vs Vue 3 (深度对比)
核心差异分析: Vue 3 不仅仅是 API 的改变,更到底层响应式系统的重构。
- Object.defineProperty 痛点:Vue 2 初始化时需要递归遍历
data对象的所有属性,如果对象层级深,性能开销大。且无法监听对象属性的新增/删除(需用$set)和数组下标的变化。 - Proxy 优势:Vue 3 使用
Proxy代理整个对象,惰性处理(只有访问到深层属性时才代理),性能大幅提升。且原生支持监听数组索引和Map/Set。
代码对比:
javascript
export default {
data() {
return { count: 0 }
},
methods: {
increment() {
this.count++
}
}
}javascript
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
}2. TypeScript vs JavaScript
| 维度 | JavaScript (JS) | TypeScript (TS) |
|---|---|---|
| 类型系统 | 动态弱类型 (运行时确定) | 静态强类型 (编译时检查) |
| 开发体验 | 灵活但易出错,重构风险大 | 智能提示,自动补全,重构安全 |
代码示例:
typescript
// Interface 定义接口
interface User {
id: number;
name: string;
age?: number; // 可选属性
}
// 泛型 (Generics) 增强复用性
function getFirst<T>(arr: T[]): T {
return arr[0];
}
const num = getFirst<number>([1, 2, 3]); // 类型安全3. Vue 3 初始化流程
- createApp: 调用
createApp创建应用实例。 - Use Plugins: 注册全局插件。
- Mount: 挂载到 DOM 节点。
代码示例:
javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router) // 注册插件
app.mount('#app') // 挂载4. Vue Router 钩子函数
| 钩子类型 | 名称 | 触发时机 |
|---|---|---|
| 全局 | beforeEach | 路由跳转前 (权限拦截) |
| 组件内 | beforeRouteEnter | 进入组件前 (无 this) |
代码示例 (全局守卫):
javascript
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (to.meta.requiresAuth && !token) {
next('/login') // 重定向到登录
} else {
next() // 放行
}
})5. Vuex 核心概念
| 模块 | 作用 | 调用方式 |
|---|---|---|
| State | 存储状态 | this.$store.state |
| Mutations | 同步修改 | commit('SET_USER', payload) |
| Actions | 异步操作 | dispatch('fetchUser') |
代码示例:
javascript
// store.js
const store = createStore({
state: { count: 0 },
mutations: {
INCREMENT(state) { state.count++ }
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => commit('INCREMENT'), 1000)
}
}
})6. nextTick 原理
- 作用:将回调推迟到下一个 DOM 更新周期之后执行。
- 原理:Vue 内部维护一个异步队列 (MicroTask > MacroTask)。
javascript
this.msg = 'Hello'
console.log(this.$el.textContent) // 旧值: ''
this.$nextTick(() => {
console.log(this.$el.textContent) // 新值: 'Hello'
})7. keep-alive
- 作用:缓存组件实例,避免重复销毁/重建。
- 属性:
include(缓存谁),exclude(不缓存谁)。
代码示例:
html
<!-- 缓存 name 为 Home 的组件 -->
<keep-alive include="Home">
<router-view></router-view>
</keep-alive>8. Hash vs History 路由
| 模式 | URL 示例 | 原理 |
|---|---|---|
| Hash | /#/home | window.onhashchange |
| History | /home | history.pushState |
代码示例 (Nginx 配置 History 模式):
nginx
location / {
try_files $uri $uri/ /index.html; # 404 重定向到 index.html
}9. JS 原型链
- 查找规则:实例 -> 构造函数原型 -> Object原型 -> null。
javascript
function Person() {}
const p = new Person()
// 实例的隐式原型 === 构造函数的显式原型
p.__proto__ === Person.prototype // true
// 原型链终点
Object.prototype.__proto__ === null // true10. this 指向规则
| 调用方式 | this 指向 | 示例 |
|---|---|---|
| 隐式绑定 | 调用者对象 | obj.fn() |
| 显式绑定 | 指定对象 | fn.call(ctx) |
| 箭头函数 | 外层作用域 | () => {} |
代码示例:
javascript
const obj = {
name: 'Tom',
say: function() { console.log(this.name) }, // this -> obj
arrowSay: () => { console.log(this.name) } // this -> window/undefined
}11. 浏览器渲染原理
- 解析: HTML -> DOM, CSS -> CSSOM。
- 合成: DOM + CSSOM -> Render Tree。
- 绘制: Layout (回流) -> Paint (重绘) -> Composite (合成)。
12. 事件机制
- 流程: 捕获 -> 目标 -> 冒泡。
代码示例:
javascript
// 第三个参数 true 开启捕获监听
el.addEventListener('click', handler, true)
// 阻止冒泡
function handler(e) {
e.stopPropagation()
}360 (北京)
📌 面试概览
- 时长:40分钟
- 核心环节:实习经历深挖 + 前端基础 (HTML/CSS/JS) + 框架原理
- 业务:大模型基建平台
📝 知识点深度解析
1. HTML 基础:ID vs Class
| 特性 | ID | Class |
|---|---|---|
| 唯一性 | 全局唯一 | 可复用 |
| 权重 | 100 | 10 |
代码示例:
css
#header { color: red; } /* 权重高 */
.text { color: blue; } /* 权重低 */2. 框架 vs 原生 JS
- 原生 JS: 手动操作 DOM,繁琐。
- 框架: 数据驱动,虚拟 DOM 优化性能。
代码对比 (更新文本):
javascript
// 原生 JS
document.getElementById('app').innerText = 'Hello'
// Vue
this.msg = 'Hello' // 自动更新视图3. 相等性判断 == vs ===
javascript
1 == '1' // true (隐式转换)
1 === '1' // false (类型不同)
null == undefined // true (特例)4. Flex 布局体系
代码示例 (常用布局):
css
.container {
display: flex;
justify-content: space-between; /* 两端对齐 */
align-items: center; /* 垂直居中 */
}5. 水平垂直居中方案
方案一:Flex (推荐)
css
.parent {
display: flex;
justify-content: center;
align-items: center;
}方案二:Absolute + Transform
css
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}6. 数组判断方法
javascript
const arr = []
// 1. Array.isArray (推荐)
Array.isArray(arr) // true
// 2. instanceof
arr instanceof Array // true
// 3. toString (最通用)
Object.prototype.toString.call(arr) // "[object Array]"7. 变量声明 var vs let vs const
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数 | 块级 | 块级 |
| 提升 | undefined | TDZ | TDZ |
代码示例:
javascript
console.log(a) // undefined
var a = 1
console.log(b) // ReferenceError
let b = 28. v-show vs v-if
代码示例:
html
<!-- v-show: display: none (DOM 还在) -->
<div v-show="isVisible">Tab Content</div>
<!-- v-if: DOM 移除 (完全销毁) -->
<div v-if="isAdmin">Admin Panel</div>9. 组件通信
代码示例 (父子通信):
vue
<!-- Parent.vue -->
<Child :msg="parentMsg" @update="handleUpdate" />
<!-- Child.vue -->
<script setup>
defineProps(['msg'])
const emit = defineEmits(['update'])
function click() { emit('update', 'newData') }
</script>10. 异步请求处理
Fetch + Async/Await 示例:
javascript
async function fetchData() {
try {
const res = await fetch('/api/user')
const data = await res.json()
console.log(data)
} catch (err) {
console.error('Network Error:', err)
}
}
---
## TCL新技术 (深圳) {#tcl-sz}
### 📌 面试概览
- **业务**:智能终端、IoT
- **特点**:考察 Vue2/3 迁移能力、工程化工具对比。
### 📝 核心知识点解析
#### 1. Vue 2 vs Vue 3 (响应式原理)
- **Vue 2**: `Object.defineProperty`。
- **缺点**: 无法监听新增/删除属性,无法监听数组下标变化,初始化需递归遍历 (慢)。
- **Vue 3**: `Proxy`。
- **优点**: 代理整个对象,支持数组/Map/Set,惰性处理深层嵌套 (快)。
#### 2. Vue 组件通信差异 (Vue 2 vs Vue 3)
- **Vue 2**:
- `props` / `$emit`
- `$on` / `$emit` (EventBus)
- `$parent` / `$children`
- `.sync` 修饰符
- **Vue 3**:
- **移除**: `$on`, `$off`, `$once` (EventBus 需引入 `mitt` 库)。
- **移除**: `$children`。
- **变更**: `.sync` 被移除,统一合并到 `v-model`。
- **新增**: `provide/inject` (Composition API 风格), `attrs` (包含 class/style)。
#### 3. v-for 中 Key 的作用
- **作用**: 唯一标识 VNode。
- **原理**: 在 Diff 算法中,Vue 通过 Key 判断新旧节点是否是同一个。
- **无 Key**: 采用“就地更新”策略,复用 DOM 元素,只修改内容。可能导致 input 输入框状态错乱。
- **有 Key**: 准确找到对应节点,进行移动或销毁重建。
#### 4. v-model 原理与多组件场景
- **Vue 2**:
- `<input v-model="val">` -> `:value="val" @input="val = $event"`
- **Vue 3**:
- `<input v-model="val">` -> `:modelValue="val" @update:modelValue="val = $event"`
- **多个 v-model (Vue 3)**:
- `<Comp v-model:title="t" v-model:content="c" />`
- 极大地增强了组件灵活性。
#### 5. 图片懒加载
- **原生**: `<img loading="lazy" src="...">`
- **JS 实现**:
- `IntersectionObserver` 监听元素是否进入视口。
- 进入后将 `data-src` 赋值给 `src`。
#### 6. Vue 生命周期:发送请求
- **最佳时机**: `created` (Vue 2) 或 `onMounted` (Vue 3)。
- **created**: 组件实例已创建,数据已初始化,但 DOM 未挂载。适合纯数据请求。
- **mounted**: DOM 已挂载。如果请求依赖 DOM (如 ECharts),必须在这里。
#### 7. 场景题:表单删除
- **需求**: 列表中删除一项。
- **实现**:
```javascript
// 方法一: Splice (改变原数组)
this.list.splice(index, 1);
// 方法二: Filter (生成新数组, React 常用)
this.list = this.list.filter(item => item.id !== id);8. Three.js 基础 (Web3D)
- 核心三要素:
- Scene (场景): 容器,容纳所有物体。
- Camera (相机):
PerspectiveCamera(透视): 近大远小,模拟人眼。OrthographicCamera(正交): 远近一样大,用于工程制图/UI。
- Renderer (渲染器): 将场景+相机渲染到 Canvas 上。
9. Webpack vs Vite
- Webpack: Bundle Based,启动慢,热更新慢。
- Vite: Native ESM,启动快 (秒开),热更新快。
10. CSS 盒模型
- 标准盒模型:
width= content。 - 怪异盒模型:
width= content + padding + border。 - 设置:
box-sizing: border-box;
纷享销客 (深圳)
📌 面试概览
- 业务:CRM 系统 (SaaS)
- 特点:追问底层原理 (HTTPS, 内存泄漏, 深拷贝细节)。
- 体验:体验一般,面试官声音小,较真,半小时结束。
📝 核心知识点解析
1. HTTPS 深度拷打
- HTTP vs HTTPS:
- HTTP: 明文传输,端口 80。
- HTTPS: SSL/TLS 加密传输,端口 443。
- HTTPS 能被抓包吗?: 能。
- 原理: 中间人攻击 (MITM)。抓包工具 (Fiddler/Charles) 伪装成服务器向客户端发证书。
- 前提: 客户端必须手动信任抓包工具生成的 CA 根证书。
- 公钥私钥问题:
- 面试官质疑: "公钥大家都拿得到,那不是泄密了?"
- 正解:
- 公钥加密,私钥解密: 客户端用公钥加密数据,只有持有私钥的服务器能解开。黑客拿到公钥没用,解不开数据。
- 私钥签名,公钥验签: 服务器用私钥签名,客户端用公钥验证身份。
2. 内存泄漏 (Memory Leak)
- 根本原因: 不再需要的内存数据,未能被垃圾回收器 (GC) 释放。
- 常见场景:
- 闭包: 函数内部引用了外部变量,且函数被外部持有。
- 全局变量: 意外创建的全局变量。
- 定时器:
setInterval未清除。 - DOM 引用: JS 中持有已删除 DOM 节点的引用。
3. 深拷贝细节 (递归 + Map)
- Map 存哪里?:
- 存在递归函数的参数中。作为
WeakMap传递给下一层。 - 作用: 记录已拷贝的对象,防止循环引用导致栈溢出。
- 存在递归函数的参数中。作为
- 实现要点:javascript
function deepClone(target, map = new WeakMap()) { if (typeof target === 'object') { let cloneTarget = Array.isArray(target) ? [] : {}; // 检查循环引用 if (map.get(target)) return map.get(target); map.set(target, cloneTarget); for (const key in target) { cloneTarget[key] = deepClone(target[key], map); } return cloneTarget; } else { return target; } }
4. 原型链与继承
- 原型链: 实例
__proto__-> 构造函数prototype-> Objectprototype->null。 - 继承举例 (Class 继承):javascript
class Parent { constructor(name) { this.name = name; } say() { console.log(this.name); } } class Child extends Parent { constructor(name, age) { super(name); // 调用父类构造函数 this.age = age; } }
5. SSR (服务端渲染) 实现原理
- 核心: 在 Node.js 环境中执行 Vue/React 代码,生成 HTML 字符串。
- 流程:
- 客户端请求 URL。
- Node 服务器获取数据。
renderer.renderToString(app)将组件转为 HTML。- 注入到 HTML 模板中返回给浏览器。
- 浏览器进行 Hydration (注水),绑定事件,使其变活。
6. 调试技巧 (Debugger)
- 代码中: 写入
debugger;语句。 - 断点类型:
- Conditional Breakpoint: 条件断点 (右键断点 ->
i === 5时暂停)。 - XHR Breakpoint: 请求断点。
- DOM Breakpoint: 节点属性变化时暂停。
- Conditional Breakpoint: 条件断点 (右键断点 ->
7. 首屏渲染优化 (细分)
- 网络: DNS Prefetch, CDN, HTTP/2。
- 资源: 路由懒加载, 图片 WebP, Gzip/Brotli。
- 代码: Tree Shaking, 骨架屏, SSR。
百度 (深圳)
📌 面试概览
- 岗位:前端日常实习
- 特点:项目拷打深度高,考察 Web3D、GIS 渲染及工程化。
📝 核心知识点解析
1. GIS 地图渲染与缓存
- 渲染: 瓦片技术 (Tile)。将大地图切割成小块,按需加载。
- 缓存:
- 浏览器: HTTP 强缓存。
- IndexedDB: 存储离线瓦片数据,支持海量数据存储 (GB 级别)。
2. 事件委托 (Event Delegation)
- 原理: 利用事件冒泡机制,在父元素监听子元素事件。
- 优点: 节省内存,支持动态生成的 DOM。
3. Webpack 优化与工具对比
- 优化:
thread-loader(多进程),dll(预编译, 现多用缓存代替),splitChunks。 - 工具:
- Vite: 开发环境秒开,基于 ESM。
- Rollup: 适合库开发,产物更纯净。
4. 手撕防抖 (Debounce)
javascript
function debounce(fn, delay) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}5. Linux 常用指令
ls(列出目录),cd(切换),pwd(当前路径)。top(监控 CPU),tail -f(查看日志),grep(搜索关键字)。ps -ef(查看进程),netstat -anp(查看端口)。
百度 YY (广州)
📌 面试概览
- 业务:YY 直播 PC 端与 H5 端。
- 特点:考察 JS 内存模型、TS 配置、React 深度原理。
📝 核心知识点解析
1. JS 栈 (Stack) vs 堆 (Heap)
- 栈: 存储基本类型 (
number,string,boolean,null,undefined) 和引用类型的指针。速度快,空间固定。 - 堆: 存储引用类型 (
Object,Array,Function)。 - 为什么引用类型存堆?:
- 引用类型大小不固定,可能动态增长。
- 堆空间大,允许存储复杂数据结构。
- 栈是按序排列的,如果把大对象存栈,会严重影响查找速度。
2. TS 泛型与配置
- 泛型: 在定义函数/类时不指定类型,在使用时才指定。增强复用性。
- tsconfig.json:
- strict: 开启严格模式 (包含
noImplicitAny,strictNullChecks等)。 - target: 编译后的 JS 版本 (如
ES5,ESNext)。 - include / exclude: 指定编译器包含或排除的文件夹。
- strict: 开启严格模式 (包含
3. 移动端响应式 (rem vs vw)
- rem: 相对于根元素
html的font-size。- 逻辑: 通过 JS 监听窗口变化,动态修改
html的font-size。
- 逻辑: 通过 JS 监听窗口变化,动态修改
- vw: 视口单位。
1vw= 视口宽度的 1%。- 原理: 基于浏览器视口宽高计算,无需 JS 参与。
4. React 函数组件 vs 类组件
- 类组件: 使用 ES6 Class,有生命周期,有
this,有状态。 - 函数组件: 纯函数,Hooks 出现后可拥有状态。更简洁,易于测试,逻辑复用方便。
- useEffect 依赖项:
- 空数组
[]: 仅在挂载/卸载时执行。 - 有值
[a, b]: 当 a 或 b 变化时重新执行。
- 空数组
- useState 实现“同步”: 使用函数式更新。javascript
setCount(prevCount => prevCount + 1); // 获取最新的 state
