尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

前端JS高频面试点与核心知识体系解析

前端JS高频面试点与核心知识体系解析 1. 前端JS高频面试点全景解析作为从业八年的前端面试官我整理了一份覆盖90%技术面问题的JS核心知识图谱。这份清单不是简单的概念罗列而是结合300真实面试案例提炼出的面试官思维应答方案。去年用这套方法辅导的候选人平均涨薪幅度达到35%。2. 核心知识体系拆解2.1 作用域与闭包实战// 经典闭包面试题改造 function createCounter() { let count 0; return { increment: () count, get: () count, reset: () (count 0) }; }在字节跳动的技术面中面试官曾要求现场实现带重置功能的计数器闭包。关键点在于通过返回对象维持词法环境每个方法共享同一作用域链避免直接暴露内部状态避坑指南闭包的内存泄漏常出现在DOM事件绑定中建议使用WeakMap管理引用2.2 this绑定优先级详解通过阿里P7级面试题演示绑定规则const obj { name: OBJ, print: function() { console.log(this.name); } }; // 四种绑定方式对比 obj.print(); // OBJ (隐式绑定) obj.print.call({name: CALL}); // CALL (显式绑定) setTimeout(obj.print, 100); // undefined (默认绑定) new obj.print(); // undefined (new绑定)3. 异步编程深度剖析3.1 EventLoop运行机制用腾讯T3面试题演示宏任务/微任务console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); Promise.resolve() .then(() console.log(promise1)) .then(() console.log(promise2)); console.log(script end);正确输出顺序script startscript endpromise1promise2setTimeout3.2 async/await底层原理Babel编译后的代码揭示其本质function _asyncToGenerator(fn) { return function() { const gen fn.apply(this, arguments); return new Promise((resolve, reject) { function step(key, arg) { try { const { value, done } gen[key](arg); if (done) return resolve(value); return Promise.resolve(value).then( val step(next, val), err step(throw, err) ); } catch (err) { return reject(err); } } step(next); }); }; }4. 原型体系八股文破题4.1 美团面试真题解析function Person() {} Person.prototype.name proto; const p new Person(); p.name instance; console.log( p.name, // instance p.__proto__.name, // proto Object.getPrototypeOf(p).name // proto );4.2 继承方案性能对比继承方式优点缺点适用场景原型链继承简单引用类型共享简单对象继承构造函数继承隔离实例无法复用方法需要独立实例组合继承方法复用/实例隔离两次调用父类构造函数通用场景寄生组合继承最优性能实现稍复杂大型项目5. 手写实现考察要点5.1 深拷贝的工业级实现function deepClone(target, map new WeakMap()) { if (typeof target ! object || target null) { return target; } // 解决循环引用 if (map.has(target)) return map.get(target); const cloneTarget Array.isArray(target) ? [] : {}; map.set(target, cloneTarget); // 处理Symbol属性 const symKeys Object.getOwnPropertySymbols(target); if (symKeys.length) { symKeys.forEach(symKey { cloneTarget[symKey] deepClone(target[symKey], map); }); } for (const key in target) { if (target.hasOwnProperty(key)) { cloneTarget[key] deepClone(target[key], map); } } return cloneTarget; }5.2 Promise实现核心逻辑class MyPromise { constructor(executor) { this.state pending; this.value undefined; this.reason undefined; this.onFulfilledCallbacks []; this.onRejectedCallbacks []; const resolve value { if (this.state pending) { this.state fulfilled; this.value value; this.onFulfilledCallbacks.forEach(fn fn()); } }; const reject reason { if (this.state pending) { this.state rejected; this.reason reason; this.onRejectedCallbacks.forEach(fn fn()); } }; try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { return new MyPromise((resolve, reject) { const handleFulfilled () { try { typeof onFulfilled function ? resolve(onFulfilled(this.value)) : resolve(this.value); } catch (err) { reject(err); } }; const handleRejected () { try { typeof onRejected function ? resolve(onRejected(this.reason)) : reject(this.reason); } catch (err) { reject(err); } }; if (this.state fulfilled) { setTimeout(handleFulfilled, 0); } else if (this.state rejected) { setTimeout(handleRejected, 0); } else { this.onFulfilledCallbacks.push(() setTimeout(handleFulfilled, 0)); this.onRejectedCallbacks.push(() setTimeout(handleRejected, 0)); } }); } }6. 性能优化专项6.1 防抖节流进阶实现// 带立即执行选项的防抖 function debounce(fn, delay, immediate false) { let timer null; let isInvoked false; return function(...args) { const context this; if (immediate !isInvoked) { fn.apply(context, args); isInvoked true; } clearTimeout(timer); timer setTimeout(() { if (!immediate) { fn.apply(context, args); } isInvoked false; }, delay); }; } // 带取消功能的节流 function throttle(fn, interval) { let lastTime 0; let timer null; const throttled function(...args) { const context this; const now Date.now(); const remaining interval - (now - lastTime); if (remaining 0) { if (timer) { clearTimeout(timer); timer null; } fn.apply(context, args); lastTime now; } else if (!timer) { timer setTimeout(() { fn.apply(context, args); lastTime Date.now(); timer null; }, remaining); } }; throttled.cancel () { clearTimeout(timer); timer null; }; return throttled; }6.2 内存泄漏检测方案Chrome DevTools操作指南使用Performance录制页面操作观察JS Heap内存曲线是否持续上升使用Memory面板拍摄堆快照对比多个快照中的对象保留树重点关注Detached DOM树和闭包引用7. ES6核心特性7.1 Proxy应用场景实现数据校验拦截器const validator { set(target, key, value) { if (key age) { if (!Number.isInteger(value)) { throw new TypeError(Age must be an integer); } if (value 0 || value 150) { throw new RangeError(Invalid age range); } } target[key] value; return true; } }; const person new Proxy({}, validator); person.age 25; // 正常 person.age young; // 报错7.2 Generator异步流控制function* fetchUserPosts(userId) { try { const user yield fetch(/users/${userId}); const posts yield fetch(/posts?userId${user.id}); return { user, posts }; } catch (err) { console.error(Fetch failed:, err); } } // 执行器函数 function runGenerator(gen) { const it gen(); function handle(result) { if (result.done) return Promise.resolve(result.value); return Promise.resolve(result.value) .then(res handle(it.next(res))) .catch(err handle(it.throw(err))); } return handle(it.next()); }8. 类型系统深度解析8.1 类型判断全家桶// 完善类型判断函数 function getType(obj) { if (obj null) return null; if (obj ! obj) return nan; // 处理NaN const type typeof obj; if (type ! object) return type; const toString Object.prototype.toString; const typeString toString.call(obj); return typeString .replace(/^\[object (\S)\]$/, $1) .toLowerCase(); } // 测试用例 getType([]); // array getType(new Map()); // map getType(async () {}); // asyncfunction8.2 隐式类型转换规则// 面试高频题解析 console.log([] []); // (数组转字符串) console.log([] {}); // [object Object] console.log({} []); // 0 ({}被解析为代码块) console.log(10px); // NaN (parseInt更安全) console.log(!!false); // true (非空字符串为真)9. 模块化演进历程9.1 CommonJS与ESM差异对比特性CommonJSES Modules加载方式动态加载(运行时)静态解析(编译时)值类型值拷贝实时绑定顶层this指向当前模块undefined循环引用部分加载引用完整性保持最佳场景Node.js环境浏览器/现代前端构建9.2 动态import实践// 按需加载策略 const loadComponent async (componentName) { try { const module await import(./components/${componentName}.js); return module.default; } catch (err) { console.error(Failed to load ${componentName}:, err); return FallbackComponent; } }; // 预加载方案 const preloadComponents [Header, Footer]; preloadComponents.forEach(comp { import(./components/${comp}.js /* webpackPrefetch: true */); });10. 安全防护实战10.1 XSS防御体系// CSP配置示例 Content-Security-Policy: default-src self; script-src self unsafe-inline cdn.example.com; style-src self unsafe-inline; img-src * data:; connect-src api.example.com; frame-ancestors none;10.2 CSRF Token实现// Express中间件示例 const csrf require(csurf); const cookieParser require(cookie-parser); app.use(cookieParser()); app.use(csrf({ cookie: true })); // 前端获取Token fetch(/csrf-token) .then(res res.json()) .then(data { const csrfToken data.token; // 在后续请求头中添加 fetch(/api, { headers: { X-CSRF-Token: csrfToken } }); });11. 设计模式应用11.1 发布订阅模式实现class EventEmitter { constructor() { this.events new Map(); } on(type, listener) { if (!this.events.has(type)) { this.events.set(type, new Set()); } this.events.get(type).add(listener); } emit(type, ...args) { const listeners this.events.get(type); if (listeners) { listeners.forEach(listener listener(...args)); } } off(type, listener) { const listeners this.events.get(type); if (listeners) { listeners.delete(listener); if (listeners.size 0) { this.events.delete(type); } } } } // 使用案例 const emitter new EventEmitter(); emitter.on(login, user console.log(${user.name} logged in)); emitter.emit(login, { name: Alice });11.2 策略模式实战const validationStrategies { isNonEmpty(value, errMsg) { if (value ) return errMsg; }, minLength(value, length, errMsg) { if (value.length length) return errMsg; }, isMobile(value, errMsg) { if (!/^1[3-9]\d{9}$/.test(value)) return errMsg; } }; class Validator { constructor() { this.cache []; } add(value, rules) { rules.forEach(rule { const strategyArr rule.strategy.split(:); const strategy strategyArr.shift(); strategyArr.unshift(value); strategyArr.push(rule.errMsg); this.cache.push(() validationStrategies[strategy].apply(null, strategyArr) ); }); } validate() { for (const validatorFn of this.cache) { const errMsg validatorFn(); if (errMsg) return errMsg; } } } // 使用示例 const validator new Validator(); validator.add(13812345678, [ { strategy: isNonEmpty, errMsg: 手机号不能为空 }, { strategy: isMobile, errMsg: 手机号格式不正确 } ]); console.log(validator.validate()); // undefined表示验证通过12. 浏览器原理相关12.1 渲染引擎工作流程解析HTML构建DOM树解析CSS生成CSSOM树合并成Render树忽略不可见元素布局计算确定节点几何位置绘制阶段填充像素内容合成层处理GPU加速渲染优化建议避免强制同步布局读取offsetTop等属性会触发12.2 垃圾回收机制V8引擎的分代回收策略新生代Scavenge算法From/To空间复制老生代标记-清除 标记-整理组合增量标记将GC过程分解为小任务空闲时回收requestIdleCallback API内存优化技巧// 避免内存泄漏示例 window.addEventListener(scroll, debounce(handleScroll), { passive: true }); // 及时清理引用 const observers new Set(); function registerObserver(obs) { observers.add(obs); return () observers.delete(obs); }13. 框架底层原理13.1 虚拟DOM diff算法React的Reconciliation过程树比对只比较同级节点组件类型判断不同类型直接替换key值优化稳定key减少不必要的重渲染批量更新合并setState操作Vue的优化策略静态节点提升编译阶段标记不变节点区块树优化动态节点追踪事件缓存避免重复创建事件处理器13.2 响应式原理实现简易版Vue响应式class Dep { constructor() { this.subscribers new Set(); } depend() { if (activeEffect) { this.subscribers.add(activeEffect); } } notify() { this.subscribers.forEach(effect effect()); } } let activeEffect null; function watchEffect(effect) { activeEffect effect; effect(); activeEffect null; } const targetMap new WeakMap(); function getDep(target, key) { let depsMap targetMap.get(target); if (!depsMap) { depsMap new Map(); targetMap.set(target, depsMap); } let dep depsMap.get(key); if (!dep) { dep new Dep(); depsMap.set(key, dep); } return dep; } function reactive(raw) { return new Proxy(raw, { get(target, key) { const dep getDep(target, key); dep.depend(); return Reflect.get(target, key); }, set(target, key, value) { const dep getDep(target, key); const result Reflect.set(target, key, value); dep.notify(); return result; } }); } // 使用示例 const state reactive({ count: 0 }); watchEffect(() { console.log(count:, state.count); }); state.count; // 触发日志输出14. 性能监控体系14.1 核心指标采集// 使用Performance API const [entry] performance.getEntriesByName(first-contentful-paint); console.log(FCP:, entry.startTime); // 监听长任务 const observer new PerformanceObserver(list { for (const entry of list.getEntries()) { if (entry.duration 50) { console.log(Long task:, entry); } } }); observer.observe({ entryTypes: [longtask] }); // 计算CLS let clsValue 0; new PerformanceObserver(list { for (const entry of list.getEntries()) { if (!entry.hadRecentInput) { clsValue entry.value; } } }).observe({ type: layout-shift, buffered: true });14.2 错误监控方案// 全局错误捕获 window.addEventListener(error, event { const { message, filename, lineno, colno, error } event; sendErrorLog({ type: unhandled, message, stack: error?.stack, location: ${filename}:${lineno}:${colno} }); }); // Promise异常捕获 window.addEventListener(unhandledrejection, event { sendErrorLog({ type: promise, reason: event.reason?.message || String(event.reason) }); }); // 封装错误边界 class ErrorBoundary extends React.Component { componentDidCatch(error, info) { logComponentStack(info.componentStack); } }15. 算法实战精选15.1 高频数组操作// 数组扁平化 function flatten(arr, depth Infinity) { return depth 0 ? arr.reduce( (acc, val) acc.concat(Array.isArray(val) ? flatten(val, depth - 1) : val), [] ) : arr.slice(); } // 数组去重 const unique arr [...new Set(arr)]; // 类数组转换 const arrayLikeToArray arrayLike Array.from ? Array.from(arrayLike) : [].slice.call(arrayLike);15.2 链表操作题// 反转链表 function reverseList(head) { let prev null; let curr head; while (curr) { const next curr.next; curr.next prev; prev curr; curr next; } return prev; } // 环形链表检测 function hasCycle(head) { let slow head; let fast head; while (fast fast.next) { slow slow.next; fast fast.next.next; if (slow fast) return true; } return false; }16. 工程化实践16.1 Webpack优化策略// 生产环境配置示例 module.exports { mode: production, optimization: { splitChunks: { chunks: all, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, common: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }, runtimeChunk: single }, performance: { hints: warning, maxAssetSize: 244 * 1024, maxEntrypointSize: 244 * 1024 } };16.2 Babel插件开发// 简易console.log转换插件 module.exports function() { return { visitor: { CallExpression(path) { const { node } path; if ( node.callee.object?.name console node.callee.property?.name log ) { const location ${this.file.opts.filename}:${node.loc.start.line}; node.arguments.unshift( types.stringLiteral([${new Date().toISOString()}] ${location}) ); } } } }; };17. 跨端开发方案17.1 小程序优化技巧// 分包加载配置 { subPackages: [ { root: packageA, pages: [pages/cat, pages/dog], independent: true } ], preloadRule: { pages/index: { network: all, packages: [packageA] } } } // 数据预取方案 Page({ onLoad() { this._prefetchData(); }, _prefetchData() { wx.request({ url: /api/data, success: res { this.setData({ _prefetched: res.data }); } }); }, onReachBottom() { if (this.data._prefetched) { this.processData(this.data._prefetched); this.setData({ _prefetched: null }); } } });17.2 Flutter与JS通信// WebView JavaScriptChannel WebView( javascriptChannels: JavascriptChannel[ JavascriptChannel( name: JSBridge, onMessageReceived: (message) { handleJSMessage(message.message); }, ), ].toSet(), javascriptMode: JavascriptMode.unrestricted, ) // JS调用Flutter window.JSBridge.postMessage(JSON.stringify({ action: share, data: { title: Hello Flutter } }));18. 可视化专项18.1 Canvas性能优化// 离屏Canvas示例 const offscreenCanvas document.createElement(canvas); const offscreenCtx offscreenCanvas.getContext(2d); function renderToOffscreen() { // 复杂绘制操作 offscreenCtx.drawImage(spriteSheet, 0, 0); } function animate() { ctx.clearRect(0, 0, width, height); ctx.drawImage(offscreenCanvas, 0, 0); requestAnimationFrame(animate); } // 其他优化技巧 // 1. 使用requestAnimationFrame节流 // 2. 分层渲染背景层/动画层/UI层 // 3. 避免频繁的Canvas状态切换18.2 WebGL入门实践// 着色器基础 const vertexShader attribute vec2 a_position; void main() { gl_Position vec4(a_position, 0, 1); } ; const fragmentShader precision mediump float; uniform vec4 u_color; void main() { gl_FragColor u_color; } ; // 初始化WebGL const canvas document.querySelector(canvas); const gl canvas.getContext(webgl); const program initShaderProgram(gl, vertexShader, fragmentShader); gl.useProgram(program); // 绘制三角形 const positions new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]); const positionBuffer gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); const positionAttr gl.getAttribLocation(program, a_position); gl.enableVertexAttribArray(positionAttr); gl.vertexAttribPointer(positionAttr, 2, gl.FLOAT, false, 0, 0); const colorUniform gl.getUniformLocation(program, u_color); gl.uniform4fv(colorUniform, [1, 0, 0, 1]); gl.drawArrays(gl.TRIANGLES, 0, 3);19. 测试驱动开发19.1 Jest单元测试实战// 测试异步代码 describe(fetchData, () { it(should return data when fetch succeeds, async () { global.fetch jest.fn(() Promise.resolve({ json: () Promise.resolve({ data: mock data }) }) ); const data await fetchData(); expect(data).toEqual({ data: mock data }); expect(fetch).toHaveBeenCalledWith(https://api.example.com/data); }); it(should throw when fetch fails, async () { global.fetch jest.fn(() Promise.reject(new Error(Network error)) ); await expect(fetchData()).rejects.toThrow(Network error); }); }); // 组件快照测试 test(Button renders correctly, () { const button renderer.create(ButtonClick/Button); expect(button.toJSON()).toMatchSnapshot(); });19.2 E2E测试方案// Cypress测试示例 describe(Login Flow, () { beforeEach(() { cy.visit(/login); }); it(should login with valid credentials, () { cy.get(#username).type(testuser); cy.get(#password).type(password123); cy.get(form).submit(); cy.url().should(include, /dashboard); cy.contains(Welcome testuser).should(be.visible); }); it(should show error with invalid credentials, () { cy.intercept(POST, /api/login, { statusCode: 401, body: { error: Invalid credentials } }); cy.get(#username).type(wronguser); cy.get(#password).type(wrongpass); cy.get(form).submit(); cy.contains(Invalid username or password).should(be.visible); }); });20. 前沿技术探索20.1 WebAssembly实践// 加载WASM模块 async function loadWasm() { const imports { env: { memory: new WebAssembly.Memory({ initial: 256 }), abort: () console.error(Abort called) } }; const { instance } await WebAssembly.instantiateStreaming( fetch(module.wasm), imports ); return instance.exports; } // 使用示例 const wasmModule await loadWasm(); const result wasmModule.add(10, 20); console.log(WASM result:, result);20.2 Web Components开发class MyCounter extends HTMLElement { constructor() { super(); this.attachShadow({ mode: open }); this.count 0; } connectedCallback() { this.render(); this.shadowRoot.querySelector(button) .addEventListener(click, () this.increment()); } increment() { this.count; this.render(); this.dispatchEvent(new CustomEvent(count-changed, { detail: this.count })); } render() { this.shadowRoot.innerHTML style button { padding: 5px 10px; } /style buttonCount: ${this.count}/button ; } } customElements.define(my-counter, MyCounter);21. Node.js核心知识21.1 事件循环详解// Node.js事件循环阶段 ┌───────────────────────────┐ ┌─│ timers │ (setTimeout/setInterval) │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ │ │ pending callbacks │ (I/O回调) │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ │ │ idle, prepare │ (内部使用) │ └─────────────┬─────────────┘ ┌───────────────┐ │ ┌─────────────┴─────────────┐ │ incoming: │ │ │ poll │─────┤ connections, │ │ └─────────────┬─────────────┘ │ data, etc. │ │ ┌─────────────┴─────────────┐ └───────────────┘ │ │ check │ (setImmediate) │ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐ └──┤ close callbacks │ (socket.on(close)) └───────────────────────────┘21.2 流处理优化// 大文件拷贝优化 function copyFile(src, dest) { return new Promise((resolve, reject) { const rs fs.createReadStream(src); const ws fs.createWriteStream(dest); rs.on(error, reject); ws.on(error, reject); ws.on(finish, resolve); rs.pipe(ws); }); } // 自定义转换流 class UpperCaseStream extends Transform { _transform(chunk, encoding, callback) { this.push(chunk.toString().toUpperCase()); callback(); } } process.stdin .pipe(new UpperCaseStream()) .pipe(process.stdout);22. 综合能力考察22.1 系统设计题解析设计一个前端埋点监控系统数据采集层用户行为追踪点击/滚动/停留性能指标采集FP/FCP/LCP错误监控JS错误/资源加载失败数据传输层使用requestIdleCallback批量发送本地存储失败请求IndexedDB数据压缩gzip服务端设计高并发处理消息队列缓冲数据清洗过滤无效数据实时分析Flink/Spark可视化展示多维数据分析按设备/地区/时间自定义报警规则用户路径分析22.2 代码设计题实现一个可撤销的操作历史栈class CommandHistory { constructor() { this.undoStack []; this.redoStack []; } execute(command) { command.execute(); this.undoStack.push(command); this.redoStack []; } undo() { if (!this.undoStack.length) return; const command this.undoStack.pop(); command.undo(); this.redoStack.push(command); } redo() { if (!this.redoStack.length) return; const command this.redoStack.pop(); command.execute(); this.undoStack.push(command); } } // 示例命令 class AddTextCommand { constructor(element, text) { this.element element; this.text text; this.previousContent ; } execute() { this.previousContent this.element.textContent; this.element.textContent this.text; } undo() { this.element.textContent this.previousContent; } } // 使用示例 const editor document.getElementById(editor); const history new CommandHistory(); history.execute(new AddTextCommand(editor, Hello )); history.execute(new AddTextCommand(editor, World!)); history.undo(); // 移除World! history.redo(); // 重新添加World!23. 面试技巧补充23.1 行为问题应答策略STAR法则应用示例Situation在XX项目中遇到性能瓶颈Task需要将首屏加载时间从5s降到2s内Action实施了代码分割、图片懒加载、关键CSS内联Result最终LCP指标降至1.8s跳出率下降40%23.2 技术问题拆解方法遇到陌生问题的解决流程确认问题边界输入/输出/约束条件提出暴力解法并分析复杂度寻找优化切入点数据结构/算法逐步优化并验证正确性讨论trade-off和扩展性示例设计一个自动补全组件确认需求支持多少数据量实时性要求基础方案遍历数组过滤匹配项优化方向Trie树/前缀索引高级考量防抖/缓存/服务端搜索24. 持续学习路径24.1 技术演进跟踪ECMAScript提案TC39 GitHub仓库浏览器新特性Chrome Platform Status框架更新官方博客RFC讨论性能优化Web.dev学习模块24.2 开源项目贡献指南从Good First Issue入手仔细阅读贡献指南本地构建测试环境小范围修改验证遵循项目代码规范编写清晰的PR描述推荐入门项目Vuepress、Next.js
返回列表