前端工程师面试高频题库解析:1000+核心考点与实战指南

一、框架原理与对比

1. Vue2与Vue3的核心差异

Vue3在响应式系统上采用Proxy替代Vue2的Object.defineProperty,解决了以下痛点:

  • 动态属性监听:Vue2无法监听对象新增/删除属性,需通过Vue.set/delete或重新赋值解决。Vue3的Proxy天然支持动态属性变化检测。
  • 性能优化:Proxy的懒代理机制减少初始化开销,配合Tree-shaking可优化打包体积。
  • 组合式API:Vue3的setup函数将逻辑按功能组织,替代Vue2的选项式API,提升代码复用性。

示例对比

  1. // Vue2 动态属性监听失效
  2. data() {
  3. return { obj: { a: 1 } }
  4. },
  5. methods: {
  6. addProp() {
  7. this.obj.b = 2 // 视图不更新
  8. }
  9. }
  10. // Vue3 Proxy方案
  11. import { reactive } from 'vue'
  12. const state = reactive({ obj: { a: 1 } })
  13. state.obj.b = 2 // 视图自动更新

2. Mixin与组件生命周期执行顺序

Mixin的合并策略遵循以下规则:

  1. 数据对象:组件数据优先,Mixin数据通过浅拷贝合并。
  2. 生命周期钩子:Mixin钩子先调用,组件钩子后调用,形成”洋葱模型”。

执行顺序示例

  1. // Mixin定义
  2. const myMixin = {
  3. created() { console.log('Mixin created') }
  4. }
  5. // 组件定义
  6. export default {
  7. mixins: [myMixin],
  8. created() { console.log('Component created') }
  9. }
  10. // 输出顺序:
  11. // Mixin created
  12. // Component created

二、工程化与构建工具

1. Vite与主流构建工具对比

Vite的核心优势在于:

  • 开发环境启动快:基于ES Module原生导入,无需打包整个应用。
  • 生产构建优化:通过Rollup进行多进程打包,支持代码分割与Tree-shaking。
  • HMR效率高:仅需更新修改的模块,而非整个应用。

对比Webpack
| 特性 | Vite | Webpack |
|———————-|——————————|———————————-|
| 启动速度 | 毫秒级 | 秒级 |
| 构建机制 | 开发ESM+生产Rollup | 全流程打包 |
| 插件生态 | 逐步完善 | 成熟丰富 |

2. 多进程打包实现方案

主流构建工具通过以下方式实现多进程:

  • Thread-loader:Webpack插件,将任务分配到worker池。
  • Parallel-uglify:并行压缩JS文件。
  • ESBuild:基于Go的极速编译器,支持转译与压缩。

配置示例

  1. // webpack.config.js
  2. module.exports = {
  3. module: {
  4. rules: [
  5. {
  6. test: /\.js$/,
  7. use: [
  8. 'thread-loader',
  9. 'babel-loader'
  10. ]
  11. }
  12. ]
  13. }
  14. }

三、语言特性与底层原理

1. importrequire的差异

特性 ES Module (import) CommonJS (require)
加载时机 静态解析(编译时) 动态加载(运行时)
提升特性 顶层import会提升 无提升
循环引用处理 返回部分完成模块 可能返回空对象
错误捕获 编译阶段报错 运行时抛出异常

错误场景示例

  1. // 编译时错误(import)
  2. import './non-existent-file.js' // 构建阶段直接报错
  3. // 运行时错误(require)
  4. try {
  5. require('./non-existent-file.js')
  6. } catch (e) {
  7. console.error(e) // 需手动捕获异常
  8. }

2. 继承的实现方式

JavaScript中继承的五种实现方案:

  1. 原型链继承:通过修改__proto__实现。
  2. 构造函数继承:在子类中调用父类构造函数。
  3. 组合继承:结合原型链与构造函数。
  4. 原型式继承:基于Object.create()
  5. 寄生组合继承:最优方案,避免重复调用父类构造。

寄生组合继承示例

  1. function Parent(name) {
  2. this.name = name
  3. }
  4. Parent.prototype.sayName = function() {
  5. console.log(this.name)
  6. }
  7. function Child(name, age) {
  8. Parent.call(this, name) // 继承属性
  9. this.age = age
  10. }
  11. // 关键步骤:继承方法
  12. Child.prototype = Object.create(Parent.prototype)
  13. Child.prototype.constructor = Child

四、性能优化与高级技巧

1. 缓存策略与ETag生成

浏览器缓存机制包含以下层级:

  1. 强缓存:通过ExpiresCache-Control控制。
  2. 协商缓存:通过Last-Modified/If-Modified-SinceETag/If-None-Match实现。

ETag生成策略

  • 文件内容哈希:如Webpack的[contenthash]
  • 版本号:结合构建时间或Git Commit Hash。
  • 混合策略:内容哈希+文件大小+修改时间。

示例配置

  1. // webpack.config.js
  2. output: {
  3. filename: '[name].[contenthash].js',
  4. chunkFilename: '[name].[contenthash].chunk.js'
  5. }

2. JSX与Render函数对比

特性 JSX Render函数
语法 XML-like语法 直接调用JS函数
编译结果 转换为React.createElement 直接返回VNode对象
灵活性 需遵循JSX语法规则 可自由控制生成逻辑
调试友好性 语法高亮与错误提示 需熟悉VNode结构

Vue中使用JSX示例

  1. export default {
  2. render() {
  3. return (
  4. <div class="container">
  5. <h1>{this.title}</h1>
  6. <button onClick={this.handleClick}>Click</button>
  7. </div>
  8. )
  9. }
  10. }

五、学习资源推荐

  1. 在线题库:某技术问答社区搜索”前端面试题库”
  2. 框架源码:官方文档的”深入原理”章节
  3. 实战项目:开源社区的明星项目(如Vue3源码解析)
  4. 性能工具:Lighthouse、Chrome DevTools

本文整理的1000+面试题覆盖了前端开发的核心知识体系,建议开发者结合实际项目理解原理,通过代码实践巩固概念。面试前可针对目标公司的技术栈重点复习相关领域,如电商类公司侧重性能优化,云服务类公司侧重工程化能力。