一、DOM事件机制与差异解析
1. 非冒泡事件类型与捕获机制
DOM事件模型包含捕获阶段、目标阶段和冒泡阶段。部分事件如focus、blur、mouseenter、mouseleave默认不冒泡,但可通过addEventListener第三个参数设为true启用捕获。例如:
document.addEventListener('focus', handler, true); // 捕获阶段触发
现代浏览器已支持focusin和focusout替代方案,它们天然支持冒泡机制。
2. mouseEnter与mouseOver的边界处理
两者核心差异在于事件触发频率:
mouseover:当鼠标进入元素或其子元素时触发mouseenter:仅当鼠标首次进入元素时触发
实现类似mouseenter的防抖效果:
element.addEventListener('mouseover', (e) => {if (e.target === element) {// 实际业务逻辑}});
二、异步编程与语言特性
3. MessageChannel的跨线程通信
作为HTML5提供的消息通道机制,MessageChannel通过两个端口(port1/port2)实现线程间通信。典型应用场景包括:
- Web Worker与主线程通信
- 微前端架构中的跨应用通信
- 性能敏感型任务的解耦执行
const channel = new MessageChannel();channel.port1.onmessage = (e) => console.log('Received:', e.data);channel.port2.postMessage('Hello');
4. async/await的底层实现
编译器将async函数转换为状态机,通过Promise链实现异步控制流。关键转换规则:
await表达式被包装为Promise.resolve()- 函数体被拆分为多个
.then()回调 - 异常通过
.catch()统一处理
V8引擎执行流程示例:
async function foo() {const a = await 1;const b = await 2;return a + b;}// 转换为function foo() {return Promise.resolve(1).then(a => Promise.resolve(2).then(b => a + b));}
三、ES6+语言特性进阶
5. Proxy的深度监听实现
默认情况下Proxy无法直接监听嵌套对象变化,需通过递归代理实现:
function deepProxy(target) {return new Proxy(target, {set(trapTarget, key, value) {console.log(`Setting ${key}`);if (typeof value === 'object' && value !== null) {value = deepProxy(value); // 递归代理}trapTarget[key] = value;return true;}});}
6. 解构赋值的类型适配
对象解构要求右侧对象包含对应属性,可通过以下方式实现数组解构对象:
// 错误示范// var [a, b] = {a: 1, b: 2}; // TypeError// 正确方案1:使用对象属性顺序const obj = {0: 'a', 1: 'b', length: 2};const arr = Array.from(obj); // ['a', 'b']// 正确方案2:自定义迭代器const iterableObj = {[Symbol.iterator]: function* () {yield this.a;yield this.b;},a: 1, b: 2};const [x, y] = iterableObj; // x=1, y=2
四、框架原理与工程实践
7. Vue3响应式系统重构
相比Vue2的Object.defineProperty,Vue3采用Proxy实现:
- 支持数组索引监听
- 避免初始化性能开销
- 提供更精确的依赖收集
响应式数据劫持核心代码:
function reactive(target) {return new Proxy(target, {get(target, key, receiver) {track(target, key); // 依赖收集return Reflect.get(...arguments);},set(target, key, value, receiver) {const result = Reflect.set(...arguments);trigger(target, key); // 触发更新return result;}});}
8. React Portals的应用场景
Portals通过ReactDOM.createPortal将子节点渲染到DOM树外节点,典型用例:
- 模态框(Modal)避免z-index冲突
- 工具提示(Tooltip)保持DOM结构清晰
- 全局通知(Notification)独立于应用布局
function Modal({ children }) {return ReactDOM.createPortal(children,document.getElementById('modal-root'));}
五、模块化与构建优化
9. CommonJS与ES Modules差异
| 特性 | CommonJS | ES Modules |
|---|---|---|
| 加载时机 | 运行时同步加载 | 静态解析阶段确定依赖 |
| 输出值 | 值的拷贝 | 值的动态引用 |
| this指向 | 指向当前模块 | 指向undefined |
| 循环依赖处理 | 可能获取不完整模块 | 通过静态分析优化 |
10. 依赖管理最佳实践
dependencies:生产环境必需的第三方包devDependencies:开发测试工具(如Webpack、Babel)peerDependencies:声明与宿主环境的兼容版本
{"dependencies": {"react": "^18.0.0"},"devDependencies": {"webpack": "^5.0.0"}}
六、性能优化与调试技巧
11. 脚本加载位置优化
<head>中加载:配合async/defer避免阻塞渲染<body>底部加载:确保DOM解析完成后再执行- 预加载策略:使用
<link rel="preload">提前获取资源
12. 生命周期钩子时机分析
Vue组件生命周期调用顺序:
父组件created -> 子组件created -> 子组件mounted -> 父组件mounted
时间差主要受以下因素影响:
- 子组件复杂度
- 网络请求耗时
- 异步渲染队列
七、面试准备策略
- 知识图谱构建:将问题分类为基础理论、框架原理、工程实践三类
- 代码手写训练:每日练习3-5个手写实现题(如bind、Promise.all)
- 系统设计模拟:针对复杂问题(如虚拟DOM实现)进行模块化拆解
- 复盘优化机制:建立错题本记录薄弱环节,定期进行知识重构
建议采用费曼学习法,对每个技术点进行”输入-处理-输出”的完整闭环训练。对于框架原理类问题,推荐结合源码调试加深理解,例如通过Vue3的响应式仓库学习Proxy的高级用法。