第 16 周总结:进阶特性 + 综合实战 — 阶段1 毕业 🎓
蜗牛往上爬 · 前端工业可视化学习笔记 第 16 周总结
本周补齐进阶特性(深浅拷贝、防抖节流、Proxy 伏笔),用毕业项目"智能设备监控台"把 16 周所学全部整合。阶段1 正式收官——你已经具备工程化思维的前端开发者地基。
目录
一、本周学了什么
知识图谱
进阶特性与综合实战
├── 进阶特性
│ ├── 浅拷贝:... / assign(嵌套共享引用)
│ ├── 深拷贝:JSON / structuredClone / 手写递归
│ ├── 内存泄漏:定时器 / 监听 / 全局变量
│ ├── Symbol:唯一值、隐藏属性
│ ├── Proxy:get/set 拦截(Vue3 响应式原理)
│ └── 防抖(停下来执行)/ 节流(固定频率)
│
└── 毕业项目:智能设备监控台
├── 分层:api → store → render → app
├── 模型:Class + getter + 静态工厂
├── 状态:Map 设备表 + Set 告警 + 模块私有
├── 异步:Promise 接口 + async/await 刷新
├── 交互:防抖搜索 + 3 秒轮询
└── 视觉:Grid 卡片 + 告警呼吸灯动画
二、核心知识速记
三条铁律
展开是浅拷贝——嵌套对象改了会连坐,需要独立就用深拷贝
定时器和监听不用就清——内存泄漏三大杀手之二
输入用防抖,滚动用节流
高频写法
// 深拷贝
const copy = structuredClone(obj);
// 防抖(闭包 + 高阶函数)
const debounce = (fn, delay = 400) => {
let timer = null;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
// 节流
const throttle = (fn, interval = 300) => {
let last = 0;
return (...args) => {
if (Date.now() - last >= interval) {
last = Date.now();
fn(...args);
}
};
};
// Proxy 拦截(Vue3 响应式雏形)
const proxy = new Proxy(data, {
get(target, key) { return target[key]; },
set(target, key, value) { target[key] = value; return true; }
});
毕业项目的数据流
setInterval(3s) → app.refresh()
→ await api.fetchDevices() # 异步拉数据
→ store.syncDevices(data) # Map/Set 更新状态
→ getStats/getDevices/getAlerts # 派生数据
→ render.xxx() # 模板字符串渲染
→ CSS 动画 # 告警呼吸灯
这就是"单向数据流"——Vue/React 框架做的事就是把这条链自动化。
三、本周踩过的坑
坑点 1:以为展开就是深拷贝
// ❌ 嵌套对象共享引用
const copy = { ...device };
copy.location.workshop = "二号";
console.log(device.location.workshop); // "二号" ⚠
// ✅ 深拷贝
const copy = structuredClone(device);
坑点 2:JSON 深拷贝丢了函数
const obj = { name: "A", fn: () => {}, date: new Date() };
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy.fn); // undefined ⚠ 函数丢了
console.log(copy.date); // 字符串,不是 Date 对象 ⚠
// 含函数/Date → 用 structuredClone 或手写递归
坑点 3:防抖函数直接绑定
// ❌ 每次绑定都创建新 timer,防抖失效
searchInput.addEventListener("input", e =>
debounce(search, 400)(e.target.value)
);
// ✅ 先创建防抖后的函数,再绑定
const debouncedSearch = debounce(search, 400);
searchInput.addEventListener("input", e => debouncedSearch(e.target.value));
坑点 4:轮询刷新覆盖了搜索状态
// ❌ 轮询时忽略关键词,搜索结果被重置
renderDevices(getDevices(), grid);
// ✅ refresh 时带上当前关键词
renderDevices(getDevices(searchInput.value.trim()), grid);
坑点 5:innerHTML 全量重建丢失输入焦点
// 搜索时重渲染整个列表 → 正在输入的 input 若也在重建范围内会失焦
// ✅ 项目里 searchInput 在列表外,不受影响
// ✅ 通用解法:只重建列表区域,不动输入框
四、自测清单
[ ] 浅拷贝和深拷贝的区别?浅拷贝的坑?
[ ] 三种深拷贝方式及各自局限?
[ ] 内存泄漏的三大来源?怎么防?
[ ] Symbol 的特性?怎么实现"隐藏属性"?
[ ] Proxy 能拦截什么?和 Vue3 什么关系?
[ ] 防抖和节流的区别?各自适合什么场景?
[ ] 防抖为什么必须用闭包?
[ ] 毕业项目的模块分层和依赖方向?
[ ] 数据从接口到页面的完整流转?
[ ] Map/Set 在项目里分别承担什么?为什么不用数组/对象?
五、阶段1 总回顾
16 周知识全景
阶段1 沉淀的作品
阶段0+1 合计
32 周 | 41+ 篇博客 | 3 个完整项目 | 静态大屏 + 交互系统 + 实时监控台
最值得记住的 10 条铁律
永远用
===,不用==默认
const,需要改用let,告别var数组按位置解构,对象按属性名解构
回调用箭头函数,对象方法用普通函数
||会误伤 0 和 “”,兜底用??去重一行:
[...new Set(arr)]fetch 必查
response.ok无依赖请求用
Promise.all并发子类 constructor 先
super()再this输入防抖、滚动节流、展开是浅拷贝
六、下一站预告
阶段2:智慧工厂大屏项目(0-3 个月)—— 第一张求职名片
阶段2 开始前建议:
用 1-2 天复习毕业项目,确保能"不看笔记"重写核心模块
整理博客目录,挑选 3-5 篇打磨成"代表作"
保持每天 2 小时节奏,学习惯性比爆发力重要
🎓 阶段1 毕业! 从 2026 年夏天那个"什么是变量"的起点,到今天能独立搭出分层架构的实时监控台——32 周,你做到了。阶段2,智慧工厂大屏见!🚀