首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >前端面试精华指南

前端面试精华指南

作者头像
木易士心
发布2025-11-30 09:14:12
发布2025-11-30 09:14:12
200
举报

一、变量与作用域

1. 核心概念
  • var / let / const 的区别
    • var:函数作用域、存在变量提升、允许重复声明。
    • let / const:块级作用域、存在暂时性死区(TDZ)、禁止重复声明。
  • 作用域类型:全局作用域、函数作用域、块级作用域。
  • 作用域链:JavaScript 引擎在查找变量时,会沿着当前作用域向上逐层搜索,直到全局作用域。
2. 高频面试题

“为什么 var 在 for 循环中会导致闭包问题?而 let 不会?”

3. 代码示例
代码语言:javascript
复制
// var:函数作用域 + 提升 → 所有回调共享同一个 i(值为 3)
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 输出:3, 3, 3
}

// let:每次循环创建新的块级绑定 → 每个闭包捕获独立的 i
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 输出:0, 1, 2
}
4. 延伸知识点
  • 暂时性死区(TDZ):在 let/const 声明前访问变量会抛出 ReferenceError
  • 全局对象差异
    • 浏览器中:var a = 1 会挂载到 window.a
    • Node.js 中:模块作用域隔离,不会污染 global

二、闭包与内存管理

1. 核心概念
  • 闭包:函数与其词法环境的组合。即使外部函数已执行完毕,内部函数仍可访问其变量。
  • 典型用途:数据封装、模块模式、防抖节流、私有变量模拟。
  • 内存泄漏风险:闭包若长期持有对 DOM 节点或大对象的引用,且未及时释放,可能导致内存无法回收。
2. 高频面试题

“如何用闭包实现一个计数器?闭包一定会导致内存泄漏吗?”

3. 代码示例
代码语言:javascript
复制
function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    decrement: () => --count,
    getCount: () => count
  };
}

const counter = createCounter();
counter.increment(); // 1
console.log(counter.getCount()); // 1
4. 延伸建议

使用 Chrome DevTools 的 Memory 面板 分析闭包引用链。

对于缓存场景,可使用 WeakMap 避免强引用导致的内存泄漏:

代码语言:javascript
复制
const cache = new WeakMap();
function memoize(fn) {
  return obj => {
    if (cache.has(obj)) return cache.get(obj);
    const result = fn(obj);
    cache.set(obj, result);
    return result;
  };
}

三、原型与继承

1.核心概念
  • prototype:构造函数的属性,指向原型对象。
  • __proto__:实例对象的内部属性,指向其构造函数的 prototype
  • ES6 class 本质仍是基于原型的语法糖。
2. 高频面试题

“什么是寄生组合式继承?为什么它是 JavaScript 继承的最佳实践?”

3. 代码示例(寄生组合继承)
代码语言:javascript
复制
function Parent(name) {
  this.name = name;
}
Parent.prototype.say = function() {
  console.log(this.name);
};

function Child(name, age) {
  Parent.call(this, name); // 借用构造函数,继承实例属性
  this.age = age;
}

// 继承原型方法
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 修复 constructor 指向

const c = new Child('Alice', 25);
c.say(); // Alice
4.延伸知识点
  • instanceof 原理:检查对象的 __proto__ 链是否包含构造函数的 prototype
  • 推荐使用 Object.getPrototypeOf()Reflect.getPrototypeOf() 获取原型。

四、异步编程演进

1. 演进路径

Callback → Promise → Generator + co → async/await

2. 高频面试题

“Promise 相比回调函数有哪些优势?”

3.代码对比
代码语言:javascript
复制
// 回调地狱(难以维护、错误处理分散)
getData(a => {
  getMoreData(a, b => {
    getEvenMore(b, c => {
      console.log(c);
    });
  });
});

// Promise 链式调用(扁平化、统一错误处理)
getData()
  .then(getMoreData)
  .then(getEvenMore)
  .then(console.log)
  .catch(err => console.error(err));

// async/await(最接近同步写法,语义清晰)
async function fetchAll() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getEvenMore(b);
    console.log(c);
  } catch (err) {
    console.error(err);
  }
}
4. 延伸建议
  • 并行请求:Promise.all([p1, p2])
  • 容错并行:Promise.allSettled()
  • 避免“async 函数滥用”:简单同步逻辑无需包装为 async

五、Promise 深度解析

1. 核心机制
  • 状态不可逆:pending → fulfilled / rejected
  • 微任务队列.then() / .catch() 回调被放入微任务队列,优先于宏任务执行。
  • 链式调用:每个 .then() 返回新 Promise,支持连续处理。
2. 高频面试题

“手写 Promise.all,并说明其行为。”

手写 Promise.all
代码语言:javascript
复制
Promise.myAll = function(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError('Argument must be an array'));
    }
    const results = new Array(promises.length);
    let completed = 0;

    if (promises.length === 0) return resolve(results);

    promises.forEach((p, i) => {
      Promise.resolve(p).then(
        val => {
          results[i] = val;
          if (++completed === promises.length) resolve(results);
        },
        err => reject(err)
      );
    });
  });
};
3. 延伸知识点
  • Promise.race():返回第一个 settled 的 Promise 结果。
  • Promise.any():返回第一个 fulfilled 的结果(ES2021)。
  • 监听未处理 rejection:window.addEventListener('unhandledrejection', ...)

六、事件循环机制(Event Loop)

1. 核心模型
  • 调用栈(Call Stack):执行同步代码。
  • 任务队列
    • 宏任务(Macrotask)setTimeoutsetInterval、I/O、UI 渲染
    • 微任务(Microtask)Promise.thenqueueMicrotaskMutationObserver
  • 执行顺序:同步代码 → 清空微任务队列 → 执行一个宏任务 → 循环
2. 高频面试题

“以下代码的输出顺序是什么?”

代码语言:javascript
复制
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);

// 输出顺序:1 → 4 → 3 → 2
3. 注意事项
  • Node.js 在 v11 之前微任务执行时机与浏览器不同,现已对齐。
  • process.nextTick()(Node.js)优先级高于 Promise.then

七、函数式编程概念

1. 核心思想
  • 纯函数:无副作用、相同输入必得相同输出。
  • 不可变性:避免直接修改原数据,返回新对象。
  • 高阶函数:接收函数作为参数或返回函数(如 mapfilterreducecompose)。
2. 高频面试题

“如何用 reduce 实现 map?如何实现函数组合(compose)?”

3. 代码示例
代码语言:javascript
复制
// 用 reduce 实现 map
Array.prototype.myMap = function(fn) {
  return this.reduce((acc, cur, i, arr) => {
    acc.push(fn(cur, i, arr));
    return acc;
  }, []);
};

// 函数组合:compose(f, g)(x) = f(g(x))
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);

const add1 = x => x + 1;
const double = x => x * 2;
const result = compose(add1, double)(5); // 11
4. 延伸建议
  • 推荐库:Ramda、Lodash/fp
  • React 中 useMemo / useCallback 本质是缓存纯函数结果,提升性能。

八、类型系统与 TypeScript

1. 核心优势
  • 编译期类型检查,提前暴露错误。
  • 更强的 IDE 智能提示、自动补全、重构支持。
  • 支持接口(interface)、泛型(Generics)、联合/交叉类型等高级特性。
2. 高频面试题

interfacetype 有什么区别?”

特性

interface

type

可扩展(声明合并)

支持计算属性

能表示原始类型

(如 type A = string)

3. 泛型实战示例
代码语言:javascript
复制
interface ApiResponse<T> {
  code: number;
  data: T;
  message: string;
}

async function request<T>(url: string): Promise<ApiResponse<T>> {
  const res = await fetch(url);
  return res.json();
}

// 使用
interface User { id: number; name: string; }
const user = await request<User>('/api/user');
4. 延伸知识点
  • Utility TypesPartial<T>Pick<T, K>Omit<T, K>Record<K, T>
  • 类型守卫:通过 typeofin、自定义函数缩小类型范围。

九、虚拟 DOM 与 Diff 算法

1. 核心概念

虚拟 DOM 是用 JS 对象描述真实 DOM 的轻量表示。当状态变化时,通过 Diff 算法 计算最小更新 patch,批量应用到真实 DOM,避免频繁重排重绘。

2. 高频面试题

“为什么不能直接操作真实 DOM?key 的作用是什么?”

3. 简易虚拟 DOM 实现
代码语言:javascript
复制
// 创建虚拟节点
function h(tag, props, children) {
  return { tag, props, children };
}

// 渲染 vnode 到真实 DOM
function render(vnode, container) {
  if (typeof vnode === 'string') {
    return document.createTextNode(vnode);
  }
  const el = document.createElement(vnode.tag);
  for (let key in vnode.props) {
    el.setAttribute(key, vnode.props[key]);
  }
  vnode.children.forEach(child => {
    el.appendChild(render(child));
  });
  if (container) container.appendChild(el);
  return el;
}

// 简易 diff(仅同层级替换)
function patch(parent, oldVNode, newVNode) {
  if (oldVNode.tag !== newVNode.tag) {
    parent.replaceChild(render(newVNode), parent.firstChild);
    return;
  }
  // 简化:直接替换子树
  const newEl = render(newVNode);
  parent.replaceChild(newEl, parent.firstChild);
}
4. key 的正确使用
代码语言:javascript
复制
//  错误:使用 index 作为 key
{list.map((item, index) => <Item key={index} value={item} />)}

//  正确:使用唯一 ID
{list.map(item => <Item key={item.id} value={item} />)}

原因:当列表发生插入/删除时,index 会错位,导致 React 复用错误的组件实例,引发状态错乱(如输入框内容错位)。

十、组件通信与状态管理

1. 通信方案对比

场景

React

Vue 3

父 → 子

props

props

子 → 父

回调函数 / useState

$emit / v-model

跨层级

Context / Zustand

provide/inject / Pinia

全局状态

Redux Toolkit / Jotai

Pinia

2. React:Context + useReducer
代码语言:javascript
复制
const AppContext = createContext();

function appReducer(state, action) {
  switch (action.type) {
    case 'SET_USER': return { ...state, user: action.payload };
    default: return state;
  }
}

export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, { user: null });
  return (
    <AppContext.Provider value={{ state, dispatch }}>
      {children}
    </AppContext.Provider>
  );
}

// 使用
const { state } = useContext(AppContext);
3. Vue 3 + Pinia
代码语言:javascript
复制
// stores/user.js
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
  state: () => ({ name: '', token: '' }),
  actions: {
    login(data) {
      this.name = data.name;
      this.token = data.token;
    }
  }
});
4. 面试回答技巧

“优先使用 props/events;跨多层用 Context/provide;复杂状态用 Redux/Pinia。避免过早引入全局状态。”

十一、性能优化实战

1. 三大方向
  • 加载性能:代码分割、懒加载、预加载、CDN
  • 运行时性能:防抖节流、虚拟滚动、React.memo
  • 内存管理:及时解绑事件、避免闭包泄漏
2. 关键代码示例
1. 懒加载组件
代码语言:javascript
复制
// React
const LazyComp = React.lazy(() => import('./HeavyComponent'));
<Suspense fallback="Loading..."><LazyComp /></Suspense>

// Vue 3
const AsyncComp = defineAsyncComponent(() => import('./Heavy.vue'));
2. 防抖函数
代码语言:javascript
复制
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}
3. 虚拟滚动(长列表)
代码语言:javascript
复制
function VirtualList({ items, itemHeight = 50 }) {
  const [scrollTop, setScrollTop] = useState(0);
  const visibleCount = Math.ceil(window.innerHeight / itemHeight);
  const start = Math.floor(scrollTop / itemHeight);
  const end = start + visibleCount;
  const visibleItems = items.slice(start, end);

  return (
    <div onScroll={e => setScrollTop(e.target.scrollTop)} style={{ height: '100vh', overflow: 'auto' }}>
      <div style={{ height: items.length * itemHeight }} />
      <div style={{ transform: `translateY(${start * itemHeight}px)` }}>
        {visibleItems.map(item => (
          <div key={item.id} style={{ height: itemHeight }}>{item.text}</div>
        ))}
      </div>
    </div>
  );
}

十二、工程化与构建工具

1. Webpack vs Vite 对比

特性

Webpack

Vite

启动速度

慢(需打包)

极快(原生 ESM)

HMR 机制

模块替换

原生 ESM 精准更新

适用场景

大型复杂项目

快速开发、中小型项目

2. 自定义 Webpack Plugin
代码语言:javascript
复制
class BundleSizePlugin {
  apply(compiler) {
    compiler.hooks.done.tap('BundleSize', stats => {
      stats.toJson().assets?.forEach(asset => {
        console.log(`${asset.name}: ${(asset.size / 1024).toFixed(2)} KB`);
      });
    });
  }
}
3. Vite 优化配置
代码语言:javascript
复制
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          utils: ['lodash', 'axios']
        }
      }
    }
  }
});
4. 面试题

“Tree Shaking 生效的前提是什么?” :使用 ES Module(静态导入)、未使用导出项、正确配置 sideEffects

十三、浏览器原理与安全

1. 渲染流程(关键六步)
  1. HTML 解析 → DOM 树
  2. CSS 解析 → CSSOM 树
  3. DOM + CSSOM → Render Tree(过滤 display: none
  4. Layout(回流):计算几何位置
  5. Paint(重绘):绘制像素
  6. Composite(合成):分层后 GPU 合成

回流(reflow)成本远高于重绘(repaint)

2. XSS 防御
代码语言:javascript
复制
//  危险
el.innerHTML = userInput;

//  安全
el.textContent = userInput; // 最佳
// 或手动转义
const escapeHtml = str => str.replace(/[&<>"']/g, m => ({
  '&': '&amp;', '<': '&lt;', '>': '&gt;',
  '"': '&quot;', "'": '&#39;'
})[m]);
3. CORS 与 Cookie 安全
代码语言:javascript
复制
// 后端(Express)
app.use(cors({ origin: 'https://your-app.com', credentials: true }));

// 前端
fetch('/api/data', { credentials: 'include' });

Cookie 安全属性

  • HttpOnly:禁止 JS 访问(防 XSS)
  • Secure:仅 HTTPS 传输
  • SameSite=Strict/Lax:防御 CSRF 攻击

总结

1. 前端工程师能力图谱

层级

能力要求

语言基础

JS 核心(作用域、闭包、原型、异步、事件循环)

框架深度

React/Vue 响应式原理、组件设计、状态管理

工程能力

构建工具、性能优化、CI/CD、监控体系

计算机基础

网络协议、浏览器原理、安全机制、数据结构

面试建议:回答时采用 “场景 → 问题 → 方案 → 权衡” 结构,展现系统思维与工程判断力。

2. 学习与准备建议

模块

实践建议

虚拟 DOM

手写 mini React,理解 patch 与 reconciliation

状态管理

对比 Context / Redux / Zustand / Pinia 适用场景

性能优化

在个人项目中跑 Lighthouse,完成一次完整优化

工程化

配置 Webpack/Vite,理解 loader/plugin 工作原理

浏览器

用 Performance 面板分析一个页面的渲染瓶颈

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、变量与作用域
    • 1. 核心概念
    • 2. 高频面试题
    • 3. 代码示例
    • 4. 延伸知识点
  • 二、闭包与内存管理
    • 1. 核心概念
    • 2. 高频面试题
    • 3. 代码示例
    • 4. 延伸建议
  • 三、原型与继承
    • 1.核心概念
    • 2. 高频面试题
    • 3. 代码示例(寄生组合继承)
    • 4.延伸知识点
  • 四、异步编程演进
    • 1. 演进路径
    • 2. 高频面试题
    • 3.代码对比
    • 4. 延伸建议
  • 五、Promise 深度解析
    • 1. 核心机制
    • 2. 高频面试题
    • 手写 Promise.all
    • 3. 延伸知识点
  • 六、事件循环机制(Event Loop)
    • 1. 核心模型
    • 2. 高频面试题
    • 3. 注意事项
  • 七、函数式编程概念
    • 1. 核心思想
    • 2. 高频面试题
    • 3. 代码示例
    • 4. 延伸建议
  • 八、类型系统与 TypeScript
    • 1. 核心优势
    • 2. 高频面试题
    • 3. 泛型实战示例
    • 4. 延伸知识点
  • 九、虚拟 DOM 与 Diff 算法
    • 1. 核心概念
    • 2. 高频面试题
    • 3. 简易虚拟 DOM 实现
    • 4. key 的正确使用
  • 十、组件通信与状态管理
    • 1. 通信方案对比
    • 2. React:Context + useReducer
    • 3. Vue 3 + Pinia
    • 4. 面试回答技巧
  • 十一、性能优化实战
    • 1. 三大方向
    • 2. 关键代码示例
      • 1. 懒加载组件
      • 2. 防抖函数
      • 3. 虚拟滚动(长列表)
  • 十二、工程化与构建工具
    • 1. Webpack vs Vite 对比
    • 2. 自定义 Webpack Plugin
    • 3. Vite 优化配置
    • 4. 面试题
  • 十三、浏览器原理与安全
    • 1. 渲染流程(关键六步)
    • 2. XSS 防御
    • 3. CORS 与 Cookie 安全
  • 总结
    • 1. 前端工程师能力图谱
    • 2. 学习与准备建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档