【ES6】day40-advanced-features

作者:mario 发布时间: 2026-08-27 阅读量:1 评论数:0

第四十天:进阶特性 — 深浅拷贝与防抖节流

蜗牛往上爬 · 前端工业可视化学习笔记 第 40 篇
阶段1 最后一课补齐进阶特性:深浅拷贝(面试必考)、内存泄漏防范、Symbol 与 Proxy(Vue3 响应式的伏笔)、防抖节流(性能优化双璧)。学完这些,你的 JS 功底就完整了。


目录


一、深拷贝与浅拷贝

const device = {
  id: "CNC-001",
  temp: 65,
  location: { workshop: "一号车间" }  // 嵌套对象
};

// ===== 浅拷贝:只复制第一层 =====
const shallow = { ...device };
shallow.location.workshop = "二号车间";
console.log(device.location.workshop);  // "二号车间" ⚠ 原对象被改了!

// ===== 深拷贝:所有层级都复制 =====
// 方式 1:JSON(简单场景)
const deep1 = JSON.parse(JSON.stringify(device));
// 局限:丢函数/undefined,Date 变字符串

// 方式 2:structuredClone(现代浏览器)
const deep2 = structuredClone(device);

// 方式 3:手写递归(面试题)
function deepClone(obj) {
  if (obj === null || typeof obj !== "object") return obj;
  if (Array.isArray(obj)) return obj.map(deepClone);
  const result = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) result[key] = deepClone(obj[key]);
  }
  return result;
}

方式

深度

局限

... / assign

嵌套共享引用

JSON 序列化

丢函数,Date 变字符串

structuredClone

不支持函数

手写递归

面试要求


二、内存泄漏三大杀手

JS 自动垃圾回收:无引用的对象会被销毁。但忘记断开引用就泄漏了:

// 1. 忘清定时器
const timer = setInterval(update, 1000);
clearInterval(timer);  // ⭐ 不用时必须清

// 2. 忘移除事件监听
el.addEventListener("click", handler);
el.removeEventListener("click", handler);  // ⭐ 不用时必须移除

// 3. 意外全局变量
function bad() {
  leaked = new Array(1000000);  // ⚠ 没 let → 全局 → 永不回收
}
// ESM 自动严格模式 → 直接报错(模块化的又一个好处)

三、Symbol 与 Proxy(了解)

// Symbol:独一无二的"隐藏"属性
const ID = Symbol("id");
const device = { [ID]: "内部编号", name: "CNC-001" };
console.log(Object.keys(device));  // ["name"](Symbol 不可见)

// Proxy:拦截对象读写(Vue3 响应式核心原理!)
const data = { temp: 65 };
const proxy = new Proxy(data, {
  get(target, key) {
    console.log(`读取 ${key}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`修改 ${key} = ${value}`);
    target[key] = value;
    return true;
  }
});
proxy.temp = 80;  // 打印"修改 temp = 80"

Proxy 就是"数据变了页面自动更新"的魔法。阶段2 学 Vue 时会再次遇到它。


四、防抖与节流

高频事件(输入、滚动、resize)不能每次都处理——两大策略:

// ===== 防抖:停下来才执行(最后一次为准)=====
function debounce(fn, delay = 500) {
  let timer = null;
  return function (...args) {
    clearTimeout(timer);  // 每次触发取消上一次
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 搜索框:停止输入 500ms 后才搜索
searchInput.addEventListener("input", debounce(e => {
  search(e.target.value);
}, 500));

// ===== 节流:固定频率执行 =====
function throttle(fn, interval = 300) {
  let last = 0;
  return function (...args) {
    const now = Date.now();
    if (now - last >= interval) {
      last = now;
      fn.apply(this, args);
    }
  };
}

// 滚动:每 300ms 最多处理一次
window.addEventListener("scroll", throttle(() => {
  console.log(window.scrollY);
}, 300));

防抖

节流

策略

停止后执行最后一次

固定间隔执行一次

场景

搜索输入、表单校验

滚动、resize

比喻

电梯等人

红绿灯放行

实现原理:两者都是闭包(timer/last 存活在闭包中跨多次调用)+ 高阶函数(返回新函数)——第 8 周的知识在这里汇合。


五、总结

特性

一句话

浅拷贝

只复制第一层,嵌套共享引用

深拷贝

structuredClone 最省心,手写递归面试必备

内存泄漏

定时器、监听、全局变量——不用就断开

Symbol

唯一值,隐藏属性

Proxy

拦截读写,Vue3 响应式原理

防抖

停下来才执行(搜索框)

节流

固定频率执行(滚动)

🎯 进阶特性补齐。下一篇是阶段1 毕业项目——智能设备监控台,把 16 周所学全部融进一个工程!

评论