
模块一基石与底层核心原理本模块为前端所有上层能力的底层支撑所有框架、工程、业务问题最终均可溯源到底层原理是面试与架构落地的核心内功。目录模块一基石与底层核心原理1. 词法作用域 闭包1.1 核心本质词法作用域静态作用域闭包Closure基础示例计数器闭包1.2 实战核心应用场景项目落地防抖/节流模块化私有变量循环事件绑定函数柯里化/函数组合记忆化缓存模块化私有变量实战代码1.3 闭包与内存泄漏常见泄漏场景解决方案1.4 WeakMap / WeakSet 闭包内存优化WeakMap 实现类私有属性2. JS 执行机制执行上下文、调用栈、事件循环2.1 执行上下文与调用栈运行底层执行上下文调用栈Call Stack变量提升与 TDZ2.2 浏览器事件循环异步核心任务分类宏任务MacroTask微任务MicroTask标准执行顺序经典推演题async/await 执行本质3. V8 垃圾回收机制内存优化核心3.1 核心回收算法标记清除3.2 分代回收机制V8 核心新生代短期存活对象老生代长期存活对象3.3 弱引用与内存优化实战开发内存优化准则4. 原型链、继承与 this 绑定4.1 原型与原型链核心原理4.2 五种继承方案优劣对比寄生组合继承标准实现4.3 this 四大绑定规则优先级new 显式 隐式 默认箭头函数 this 特性5. 前端高频手写源码5.1 防抖 Debounce基础版 立即执行版5.2 节流 Throttle时间戳版 定时器版5.3 完整版深拷贝支持循环引用/Date/RegExp5.4 Promise/A 核心手写实现完整版骨架5.5 Promise 静态方法手写all / allSettled / race5.6 异步并发调度器限制请求并发数1. 词法作用域 闭包1.1 核心本质词法作用域静态作用域JS 唯一的作用域规则。函数的作用域在代码定义阶段就已确定和函数调用位置、调用方式无关。变量的访问权限由代码书写的层级位置决定。闭包Closure函数其定义时的词法环境形成的绑定组合。当内部函数被外部返回、赋值、传参脱离原有词法作用域执行时依然会保留对定义时外层作用域变量的引用使得外层函数执行完毕后局部变量不会被 GC 回收。基础示例计数器闭包function createCounter() { let count 0; // 外层局部变量被闭包持有 return function () { return count; // 内部函数引用外层变量形成闭包 }; } const counter createCounter(); console.log(counter()); // 1 console.log(counter()); // 2 // createCounter 执行栈已弹出但 count 因闭包持续存在1.2 实战核心应用场景项目落地防抖/节流通过闭包持久保存定时器 ID、上一次执行时间戳实现函数频率控制模块化私有变量隐藏内部状态仅暴露可控 API防止全局污染循环事件绑定解决 var 变量全局穿透问题锁定每一次循环的临时变量函数柯里化/函数组合利用闭包缓存前置参数实现参数复用记忆化缓存缓存高频计算结果、接口请求结果避免重复执行模块化私有变量实战代码const userModule (function () { // 私有变量外部无法直接访问 let name default; // 暴露公共方法通过闭包访问私有变量 return { getName: () name, setName: (val) { name val; } }; })();1.3 闭包与内存泄漏核心结论闭包本身不是内存泄漏不合理的闭包引用才会导致内存泄漏。正常闭包按需持有变量使用完毕后引用断开可正常 GC。泄漏本质闭包长期持有无用大型对象/变量引用链无法断开导致内存无法释放、内存堆积。常见泄漏场景闭包引用超大对象DOM、大数组、实例仅使用部分属性整体对象被强制保留闭包被全局变量、长期存活的定时器/事件监听持有作用域无法销毁SPA 页面路由切换未销毁闭包绑定的事件、定时器解决方案无用闭包引用手动置空断开引用链内存敏感场景使用 WeakMap/WeakSet 弱引用存储数据页面销毁时清空定时器、移除事件监听1.4 WeakMap / WeakSet 闭包内存优化核心特性键为对象类型属于弱引用不影响垃圾回收。当键对象无其他强引用时会被自动 GC对应键值对自动销毁。适用场景DOM 关联数据存储、类私有属性、临时缓存、闭包临时数据WeakMap 实现类私有属性const wm new WeakMap(); class User { constructor(name) { // 私有数据实例销毁后自动回收 wm.set(this, { name, createdAt: Date.now() }); } getName() { return wm.get(this).name; } } // 实例被销毁WeakMap 对应数据自动 GC无内存残留闭包的核心是函数和其词法环境的绑定依托 JS 词法作用域特性实现变量持久化。项目中主要用闭包实现防抖节流、函数缓存和模块化私有状态管理。同时清楚闭包容易引发内存堆积在内存敏感场景会结合 WeakMap 弱引用优化手动断开无用引用避免内存泄漏问题。2. JS 执行机制执行上下文、调用栈、事件循环2.1 执行上下文与调用栈运行底层执行上下文JS 代码运行的必备环境分为 3 种全局上下文、函数上下文、eval 上下文。单个上下文核心包含变量对象、作用域链、this 指向。调用栈Call Stack遵循后进先出(LIFO)规则。函数调用时创建执行上下文压栈函数执行完毕自动弹栈清空上下文。栈溢出原因递归无终止、函数嵌套过深。变量提升与 TDZvar、函数声明存在变量提升let/const 存在暂时性死区声明前无法访问杜绝变量污染。2.2 浏览器事件循环异步核心JS 单线程运行通过事件循环实现非阻塞异步核心是同步代码、微任务、宏任务的优先级调度。任务分类宏任务MacroTasksetTimeout、setInterval、I/O 操作、UI 渲染、MessageChannel微任务MicroTaskPromise.then/catch/finally、async/await、queueMicrotask、MutationObserver标准执行顺序执行所有同步代码清空全部微任务队列取出一个宏任务执行循环往复完成事件循环调度经典推演题console.log(1); setTimeout(() console.log(2), 0); Promise.resolve().then(() console.log(3)); console.log(4); // 输出顺序1 → 4 → 3 → 2async/await 执行本质await 会阻塞当前同步代码await后续所有代码都会被封装为微任务等价于 Promise.then 回调。async function foo() { console.log(A); // 同步 await bar(); console.log(B); // 微任务 }2.3 Node.js事件循环差异Node 基于 libuv 实现事件循环分为 6 个固定阶段timers → pending callbacks → idle, prepare → poll → check → close callbacks。每个阶段拥有独立宏任务队列。特殊优先级process.nextTick Promise微任务常规宏任务JS 单线程通过事件循环实现异步核心是微任务优先于宏任务执行。每一轮事件循环都会先执行完所有同步代码、清空微任务队列再执行单个宏任务。async/await 是 Promise 和 Generator 的语法糖await 后的代码属于微任务。Node 环境多了阶段调度和 nextTick 高优先级微任务和浏览器事件循环存在明显差异。3. V8 垃圾回收机制内存优化核心3.1 核心回收算法标记清除从根对象全局、栈变量遍历标记所有可达对象执行完毕后清除所有未被标记的无效对象完美解决循环引用无法回收的问题是现代 JS 主流回收算法。3.2 分代回收机制V8 核心V8 将堆内存分为新生代、老生代针对不同生命周期对象采用不同回收算法提升回收效率、减少卡顿。新生代短期存活对象存储临时变量、短期实例、回调变量使用 Scavenge 复制算法内存分为 From、To 两个对等半区存活对象复制到 To 区清空 From 区效率极高晋升规则经历一次回收、或 To 区占用超 25%晋升老生代老生代长期存活对象存储全局对象、闭包变量、长期页面实例、DOM 对象采用 标记清除 标记压缩 组合算法标记清除清理无效对象标记压缩整理内存碎片避免内存碎片化3.3 弱引用与内存优化实战WeakMap、WeakSet、WeakRef 为弱引用类型不阻止垃圾回收是前端内存优化的核心方案。FinalizationRegistry 可监听对象回收触发后置清理回调慎用回调执行时机不固定。开发内存优化准则禁止全局无节制挂载冗余属性页面销毁、组件卸载时清空定时器、移除事件监听、断开闭包引用缓存、临时数据优先使用弱引用存储自动释放无效内存4. 原型链、继承与 this 绑定4.1 原型与原型链核心原理所有函数拥有 prototype 原型对象存储实例共享属性和方法所有实例通过 __proto__ 指向构造函数原型对象。层层向上查找最终指向 Object.prototype终点为 null构成原型链。属性查找规则自身属性 → 原型链逐层向上查找 → 找不到返回 undefinedfunction Person(name) { this.name name; } // 原型挂载共享方法 Person.prototype.sayHi function () { console.log(Hi); }; const p new Person(Alice); p.sayHi(); console.log(p.__proto__ Person.prototype); // true console.log(Person.prototype.__proto__ Object.prototype); // true4.2 五种继承方案优劣对比原型链继承Child.prototype new Parent()缺点引用类型属性共享、无法向父类传参构造函数继承Parent.call(this)缺点无法继承原型方法无法复用组合继承原型链 构造函数缺点父类构造执行两次存在冗余寄生组合继承最优原生继承方案无冗余、可传参、方法复用ES6 class extends语法糖底层基于寄生组合继承实现项目首选寄生组合继承标准实现function inheritPrototype(Child, Parent) { // 继承父类原型 Child.prototype Object.create(Parent.prototype); // 修复构造器指向 Child.prototype.constructor Child; }4.3 this 四大绑定规则优先级new 显式 隐式 默认默认绑定独立函数调用非严格指向 window严格模式 undefined隐式绑定obj.foo()this 指向调用对象存在隐式丢失问题显式绑定call/apply/bind 强制修改 this 指向new绑定构造函数调用this 指向新建实例对象箭头函数 this 特性箭头函数无自身this、无prototype、无法new、无法绑定其 this 为外层词法作用域的 this完美解决回调 this 丢失问题。原型链是 JS 实现面向对象继承的底层基础现代开发优先使用 ES6 class 语法但底层依然是寄生组合继承。this 指向由调用方式而非定义方式决定遵循固定优先级。箭头函数的词法 this 特性能有效解决回调、定时器中的 this 指向丢失问题简化项目代码。5. 前端高频手写源码5.1 防抖 Debounce基础版 立即执行版// 基础延迟版 function debounce(fn, delay 300) { let timer null; return function (...args) { clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; } // 立即执行 延迟收尾版 function debounce(fn, delay, immediate false) { let timer null; return function (...args) { if (timer) clearTimeout(timer); // 立即执行 if (immediate !timer) { fn.apply(this, args); } timer setTimeout(() { timer null; // 延迟执行收尾 if (!immediate) fn.apply(this, args); }, delay); }; }5.2 节流 Throttle时间戳版 定时器版// 时间戳版立即响应尾部不执行 function throttle(fn, delay 300) { let lastTime 0; return function (...args) { const now Date.now(); if (now - lastTime delay) { lastTime now; fn.apply(this, args); } }; } // 定时器版延迟响应尾部补执行 function throttle(fn, delay 300) { let timer null; return function (...args) { if (!timer) { timer setTimeout(() { timer null; fn.apply(this, args); }, delay); } }; }5.3 完整版深拷贝支持循环引用/Date/RegExpfunction deepClone(obj, map new WeakMap()) { // 基础类型 / null 直接返回 if (obj null || typeof obj ! object) return obj; // 处理日期、正则特殊对象 if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags); // 解决循环引用 if (map.has(obj)) return map.get(obj); // 区分数组、对象创建新容器 const cloneObj Array.isArray(obj) ? [] : {}; map.set(obj, cloneObj); // 递归遍历拷贝 for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] deepClone(obj[key], map); } } return cloneObj; }5.4 Promise/A 核心手写实现完整版骨架class MyPromise { constructor(executor) { // 三种状态pending/fulfilled/rejected this.state pending; this.value undefined; this.reason undefined; // 存储异步回调队列 this.onFulfilledCallbacks []; this.onRejectedCallbacks []; const resolve (value) { if (this.state ! pending) return; this.state fulfilled; this.value value; this.onFulfilledCallbacks.forEach(fn fn()); }; const reject (reason) { if (this.state ! pending) return; this.state rejected; this.reason reason; this.onRejectedCallbacks.forEach(fn fn()); }; // 捕获执行器异常 try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { // 穿透处理 onFulfilled typeof onFulfilled function ? onFulfilled : v v; onRejected typeof onRejected function ? onRejected : err { throw err; }; const promise2 new MyPromise((resolve, reject) { // 异步调度保证微任务时序 const schedule (fn, val) { setTimeout(() { try { const x fn(val); resolvePromise(promise2, x, resolve, reject); } catch (err) { reject(err); } }); }; // 同步状态直接执行 if (this.state fulfilled) { schedule(onFulfilled, this.value); } else if (this.state rejected) { schedule(onRejected, this.reason); } else { // 异步状态存入队列 this.onFulfilledCallbacks.push(() schedule(onFulfilled, this.value)); this.onRejectedCallbacks.push(() schedule(onRejected, this.reason)); } }); return promise2; } // 异常捕获 catch(onRejected) { return this.then(null, onRejected); } } // 核心解析函数处理链式调用、Promise 嵌套 function resolvePromise(promise2, x, resolve, reject) { // 禁止循环引用 if (promise2 x) return reject(new TypeError(Chaining cycle detected for promise)); // 判断是否为 Promise if (x instanceof MyPromise) { x.then(resolve, reject); } else { resolve(x); } }5.5 Promise 静态方法手写all / allSettled / race// Promise.all全部成功才成功一个失败直接失败 Promise.myAll function (promises) { return new Promise((resolve, reject) { let count 0; const result []; const len promises.length; if (len 0) resolve([]); for (let i 0; i len; i) { Promise.resolve(promises[i]).then(res { result[i] res; count; if (count len) resolve(result); }).catch(err reject(err)); } }); }; // Promise.allSettled所有任务执行完毕返回成功/失败结果 Promise.myAllSettled function (promises) { return Promise.all(promises.map(item Promise.resolve(item) .then(value ({ status: fulfilled, value })) .catch(reason ({ status: rejected, reason })) )); }; // Promise.race谁先完成返回谁 Promise.myRace function (promises) { return new Promise((resolve, reject) { promises.forEach(item { Promise.resolve(item).then(resolve, reject); }); }); };5.6 异步并发调度器限制请求并发数class Scheduler { constructor(limit) { this.limit limit; // 最大并发数 this.queue []; // 任务等待队列 this.running 0; // 当前执行任务数 } // 添加异步任务 add(task) { return new Promise((resolve, reject) { this.queue.push(() task().then(resolve, reject)); this.run(); }); } // 执行任务 run() { while (this.running this.limit this.queue.length) { const task this.queue.shift(); this.running; task().finally(() { this.running--; this.run(); }); } } }Promise 链式调用依靠返回新 Promise、递归解析实现防抖节流依托闭包缓存变量实现频率控制并发调度器通过队列计数器实现流量管控在文件批量上传、接口限流、异步任务调度等业务场景中可以直接落地使用。