一些简单的前端资料总结

6 阅读21分钟

前端资料

涵盖 React、Next.js、Vue3、Nuxt、Node.js、NestJS 等资料


📑 目录

  1. React 资料
  2. Next.js 资料
  3. Vue3 资料
  4. Nuxt 资料
  5. Node.js 资料
  6. NestJS 资料
  7. 综合面试技巧

React 资料

🔥 核心基础

1. React 是什么?它的核心特点是什么?

答案要点:

  • 用于构建用户界面的 JavaScript 库
  • 核心特点:
    • 组件化开发
    • 虚拟 DOM(Virtual DOM)
    • 单向数据流
    • JSX 语法
    • 声明式编程
2. 什么是 JSX?浏览器能直接识别吗?

答案要点:

  • JSX 是 JavaScript 的语法扩展,允许在 JS 中编写类似 HTML 的结构
  • 浏览器不能直接识别,需要通过 Babel 等工具编译为 React.createElement() 调用
// JSX
const element = <h1 className="title">Hello</h1>;

// 编译后
const element = React.createElement('h1', { className: 'title' }, 'Hello');
3. 类组件 vs 函数组件的区别?
特性类组件函数组件
写法ES6 Class普通函数
状态管理this.stateuseState Hook
生命周期完整生命周期useEffect 等 Hooks
this 绑定需要处理 this无 this 问题
代码量相对较多简洁
4. 什么是虚拟 DOM?工作原理?

答案要点:

  • 虚拟 DOM: 用 JavaScript 对象模拟真实 DOM 结构的树形对象
  • 工作原理:
    1. 创建虚拟 DOM 树
    2. 状态变化时生成新的虚拟 DOM
    3. Diff 算法比较新旧虚拟 DOM
    4. 计算出最小变更集(patch)
    5. 批量更新真实 DOM
5. Diff 算法的核心策略?

答案要点:

  • 同层比较: 只比较同一层级的节点,不跨层级比较
  • Key 的作用: 通过 key 标识节点,提高 Diff 效率
  • 三种操作: 插入、删除、更新

⚡ Hooks 相关

6. 常用的 React Hooks 有哪些?
// useState - 状态管理
const [count, setCount] = useState(0);

// useEffect - 副作用处理
useEffect(() => {
  // 组件挂载/更新时执行
  return () => {
    // 清理函数(组件卸载时执行)
  };
}, [dependencies]);

// useContext - 上下文
const value = useContext(MyContext);

// useRef - 引用
const inputRef = useRef(null);

// useMemo - 缓存计算结果
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

// useCallback - 缓存函数
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);
7. useEffect 的依赖数组有什么作用?

答案要点:

  • [](空数组):只在组件挂载和卸载时执行
  • [a, b]:在挂载和依赖项变化时执行
  • 不写依赖数组:每次渲染都执行
8. useMemo 和 useCallback 的区别?

答案要点:

  • useMemo: 缓存函数的返回值,用于优化计算密集型操作
  • useCallback: 缓存函数本身,用于优化子组件渲染(配合 React.memo)
9. useLayoutEffect 和 useEffect 的区别?

答案要点:

  • useEffect: 异步执行,不阻塞浏览器绘制
  • useLayoutEffect: 同步执行,在浏览器绘制前执行,可能阻塞渲染
  • 使用场景: useLayoutEffect 用于需要同步执行且影响布局的操作
10. 自定义 Hook 是什么?如何编写?

答案要点:

  • 自定义 Hook 是提取组件逻辑到可复用函数的方式
  • 命名必须以 use 开头
function useWindowSize() {
  const [size, setSize] = useState({ width: 0, height: 0 });
  
  useEffect(() => {
    const handleResize = () => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  
  return size;
}

🔄 状态管理

11. React 有哪些状态管理方式?
方式适用场景特点
useState/useReducer组件级状态简单,React 内置
Context API跨组件共享避免 prop drilling,适合低频更新
Redux大型应用可预测的状态容器,单向数据流
Zustand中小型应用轻量,简洁
Jotai/Recoil原子化状态细粒度更新
React Query服务端状态数据获取、缓存、同步
12. Redux 的核心概念?

答案要点:

  • Store: 存储整个应用的状态
  • Action: 描述发生了什么的普通对象
  • Reducer: 纯函数,根据 Action 更新状态
  • 数据流: Action → Reducer → Store → View
// Action
const increment = () => ({ type: 'INCREMENT' });

// Reducer
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT': return state + 1;
    default: return state;
  }
};
13. Redux Toolkit (RTK) 的优势?

答案要点:

  • 简化 Redux 样板代码
  • 内置 Immer 支持可变语法
  • 内置 Redux Thunk 处理异步
  • 更好的 TypeScript 支持

🚀 性能优化

14. React 性能优化的方法?
// 1. React.memo - 阻止不必要的重渲染
const MyComponent = React.memo(({ data }) => {
  return <div>{data}</div>;
});

// 2. useMemo - 缓存计算结果
const expensiveValue = useMemo(() => {
  return data.filter(item => item.active);
}, [data]);

// 3. useCallback - 缓存回调函数
const handleClick = useCallback(() => {
  onAction(id);
}, [id, onAction]);

// 4. 代码分割 - 懒加载
const LazyComponent = lazy(() => import('./Component'));

// 5. Virtual List - 长列表优化
import { FixedSizeList } from 'react-window';
15. 如何避免不必要的渲染?

答案要点:

  • 使用 React.memo 包裹纯展示组件
  • 使用 useMemo 缓存复杂计算
  • 使用 useCallback 缓存函数引用
  • 合理使用 key 属性
  • 避免在 render 中创建新对象/函数

🧪 进阶问题

16. React 18 有哪些新特性?

答案要点:

  • 并发渲染(Concurrent Rendering): 可中断的渲染
  • 自动批处理(Automatic Batching): 自动合并状态更新
  • Suspense 改进: 更好的数据获取支持
  • 新的 Hooks: useId, useTransition, useDeferredValue
  • Strict Mode 改进: 双重渲染检测副作用
17. 什么是 React Server Components (RSC)?

答案要点:

  • 在服务器端执行的 React 组件
  • 可以直接访问数据库/文件系统等服务端资源
  • 不打包到客户端,减小 bundle 体积
  • Next.js App Router 已全面支持
18. React 的合成事件(SyntheticEvent)是什么?

答案要点:

  • React 封装了浏览器原生事件的跨浏览器包装器
  • 事件委托到 document 或 root 节点
  • 事件对象会被复用(pooling),异步访问需要调用 e.persist()
19. 错误边界(Error Boundary)是什么?

答案要点:

  • 捕获子组件树 JavaScript 错误
  • 防止整个应用崩溃
  • 使用 static getDerivedStateFromErrorcomponentDidCatch
  • 只能捕获类组件错误,不能捕获 Hook 和异步代码错误
20. React Fiber 架构是什么?

答案要点:

  • React 16 引入的新协调引擎
  • 将渲染工作拆分成小单元,可中断和恢复
  • 支持优先级调度,实现并发渲染
  • 为 Suspense、并发特性奠定基础

Next.js 资料

🏗️ 基础概念

21. Next.js 是什么?与 React 的区别?

答案要点:

  • Next.js: 基于 React 的全栈框架,提供服务端渲染能力
  • 核心区别:
    特性ReactNext.js
    渲染方式仅 CSRSSR、SSG、ISR、CSR
    路由需 react-router文件系统路由
    构建优化需手动配置开箱即用
    API 路由内置
    图片优化next/image
22. Next.js 的渲染模式有哪些?
模式缩写说明适用场景
服务端渲染SSR每次请求服务端渲染动态数据、SEO 要求高
静态生成SSG构建时预渲染内容不常变的页面
增量静态再生ISR构建后动态更新静态页大型静态站点
客户端渲染CSR传统 SPA 方式纯交互页面、后台系统
// SSR
export async function getServerSideProps() {
  const data = await fetchData();
  return { props: { data } };
}

// SSG
export async function getStaticProps() {
  const data = await fetchData();
  return { props: { data } };
}

// ISR
export async function getStaticProps() {
  return { 
    props: { data },
    revalidate: 60 // 60秒后重新生成
  };
}
23. App Router vs Pages Router 的区别?

答案要点:

  • Pages Router: 传统路由,基于 pages/ 目录
  • App Router: Next.js 13+ 新路由,基于 app/ 目录
特性Pages RouterApp Router
目录pages/app/
布局_app.js、_document.jslayout.js
加载状态需手动实现loading.js
错误处理需手动实现error.js
服务端组件不支持默认支持
数据获取getServerSideProps 等fetch API
24. Next.js 的路由系统如何工作?

答案要点:

pages/                  app/
├── index.js     →  /   ├── page.js       →  /
├── about.js     →  /about   ├── about/
├── blog/              │   └── page.js   →  /about
│   ├── index.js →  /blog   ├── blog/
│   └── [slug].js→  /blog/:slug  │   ├── page.js   →  /blog
└── api/               │   └── [slug]/   →  /blog/:slug
    └── hello.js →  /api/hello   │       └── page.js
25. next/image 的优势?

答案要点:

  • 自动优化图片格式和大小
  • 懒加载(Lazy Loading)
  • 防止布局偏移(CLS)
  • 响应式图片支持
  • 使用现代格式(WebP、AVIF)

⚙️ 进阶特性

26. Middleware 是什么?使用场景?

答案要点:

  • 在请求到达页面之前执行的代码
  • 使用场景:认证、重定向、A/B 测试、地理位置拦截
// middleware.js
import { NextResponse } from 'next/server';

export function middleware(request) {
  const token = request.cookies.get('token');
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*']
};
27. API Routes 如何使用?

答案要点:

// pages/api/users.js
export default function handler(req, res) {
  if (req.method === 'GET') {
    res.status(200).json({ users: [] });
  } else if (req.method === 'POST') {
    // 创建用户
    res.status(201).json({ id: 1, ...req.body });
  }
}

// app/api/users/route.js (App Router)
export async function GET() {
  const users = await db.getUsers();
  return Response.json({ users });
}

export async function POST(request) {
  const body = await request.json();
  const user = await db.createUser(body);
  return Response.json(user, { status: 201 });
}
28. 什么是 ISR(增量静态再生)?

答案要点:

  • 构建时生成静态页面
  • 运行时按指定间隔重新生成
  • 首次访问旧页面,后台生成新页面
  • 兼顾性能和实时性
export async function getStaticProps() {
  const data = await fetch('https://api.example.com/data');
  return {
    props: { data },
    revalidate: 60, // 60秒后重新验证
  };
}
29. Next.js 如何处理 SEO?

答案要点:

  • 使用 next/head 管理页面元数据
  • SSG/SSR 提供完整的 HTML 利于爬虫
  • 自动生成 sitemap.xml
  • 支持结构化数据
import Head from 'next/head';

export default function Page() {
  return (
    <>
      <Head>
        <title>页面标题</title>
        <meta name="description" content="页面描述" />
        <meta property="og:title" content="Open Graph 标题" />
      </Head>
      {/* 页面内容 */}
    </>
  );
}
30. Server Actions 是什么?

答案要点:

  • Next.js 14+ 特性
  • 在服务端执行的异步函数
  • 可直接在组件中调用,无需 API 路由
  • 自动处理 CSRF 保护
// app/actions.js
'use server';

export async function createUser(formData) {
  const name = formData.get('name');
  await db.createUser({ name });
  revalidatePath('/users');
}

// app/page.js
import { createUser } from './actions';

export default function Page() {
  return (
    <form action={createUser}>
      <input name="name" />
      <button type="submit">创建</button>
    </form>
  );
}

Vue3 资料

🎯 基础核心

31. Vue3 相比 Vue2 的主要改进?
特性Vue2Vue3
响应式原理Object.definePropertyProxy
组合式 API不支持支持 (Composition API)
性能良好提升 1.3~2 倍
TypeScript支持不佳原生支持
树摇优化有限更好的 Tree-shaking
多根节点不支持支持 (Fragments)
Teleport不支持内置支持
Suspense不支持内置支持
32. Options API vs Composition API

Options API:

export default {
  data() {
    return { count: 0 };
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  computed: {
    double() {
      return this.count * 2;
    }
  }
};

Composition API:

import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const double = computed(() => count.value * 2);
    const increment = () => count.value++;
    
    return { count, double, increment };
  }
};

// 或 <script setup> 语法糖
<script setup>
const count = ref(0);
const double = computed(() => count.value * 2);
const increment = () => count.value++;
</script>

对比:

方面Options APIComposition API
代码组织按选项类型按功能逻辑
复用逻辑Mixins(有缺点)Composables
TypeScript类型推断困难完美支持
学习曲线较平缓需理解更多概念
33. Vue3 响应式原理(Proxy vs defineProperty)

答案要点:

Vue2 - Object.defineProperty:

  • 只能劫持已存在的属性
  • 无法检测数组索引变化和对象新增属性
  • 需要递归遍历对象属性

Vue3 - Proxy:

  • 可以劫持整个对象
  • 支持数组索引和对象新增属性
  • 懒代理,性能更好
  • 13 种拦截操作
// Vue3 响应式实现简化版
function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return result;
    }
  });
}
34. ref vs reactive 的区别?
特性refreactive
数据类型任何类型仅对象/数组
访问方式.value直接访问属性
替换对象可以整体替换会丢失响应性
适用场景基础类型、需要替换的对象复杂对象、表单数据
// ref
const count = ref(0);
console.log(count.value); // 0
count.value++;

// reactive
const state = reactive({ count: 0 });
console.log(state.count); // 0
state.count++;

// 注意:解构会失去响应性
const { count } = state; // ❌ count 不是响应式的
const count = toRef(state, 'count'); // ✅ 正确做法
35. Vue3 的生命周期钩子?
// Options API → Composition API 对照
beforeCreate  →  setup() 开始
created       →  setup() 中
beforeMount   →  onBeforeMount
mounted       →  onMounted
beforeUpdate  →  onBeforeUpdate
updated       →  onUpdated
beforeUnmount →  onBeforeUnmount (Vue2: beforeDestroy)
unmounted     →  onUnmounted (Vue2: destroyed)
errorCaptured →  onErrorCaptured

// 新增
onRenderTracked   // 调试:依赖被追踪
onRenderTriggered // 调试:组件重新渲染

🔧 进阶特性

36. computed 和 watch 的区别?
特性computedwatch
用途派生状态,缓存结果监听变化,执行副作用
返回值
缓存有(依赖不变不重新计算)
适用模板中使用的计算值数据变化时执行异步/复杂操作
// computed
const fullName = computed(() => `${firstName.value} ${lastName.value}`);

// watch - 监听单个
watch(count, (newVal, oldVal) => {
  console.log(`count changed: ${oldVal}${newVal}`);
});

// watch - 监听多个
watch([count, name], ([newCount, newName]) => {
  // ...
});

// watchEffect - 自动追踪依赖
watchEffect(() => {
  console.log(count.value); // 自动追踪 count
});
37. 什么是 provide/inject?

答案要点:

  • 跨层级传递数据,避免 prop drilling
  • 祖先组件 provide,后代组件 inject
// 祖先组件
import { provide, ref } from 'vue';

const user = ref({ name: 'John' });
provide('user', user);

// 后代组件
import { inject } from 'vue';

const user = inject('user');
const user = inject('user', defaultValue); // 带默认值
38. Vue3 的 Teleport 是什么?

答案要点:

  • 将组件模板渲染到 DOM 其他位置
  • 常用于 Modal、Toast、Dialog 等
<template>
  <button @click="show = true">打开模态框</button>
  
  <Teleport to="body">
    <div v-if="show" class="modal">
      <p>模态框内容</p>
      <button @click="show = false">关闭</button>
    </div>
  </Teleport>
</template>
39. Suspense 的作用?

答案要点:

  • 处理异步依赖的组件
  • 在异步组件加载时显示 fallback 内容
<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div>加载中...</div>
    </template>
  </Suspense>
</template>
40. 自定义指令如何实现?
// 全局注册
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});

// 局部注册
const vFocus = {
  mounted(el) {
    el.focus();
  }
};

// 使用
<input v-focus />

// 简写形式(只在 mounted 和 updated 时触发)
app.directive('color', (el, binding) => {
  el.style.color = binding.value;
});

🏭 工程化

41. Vue3 的状态管理方案?

Pinia(推荐):

// stores/counter.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++;
    }
  }
});

// Composition API 风格
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0);
  const double = computed(() => count.value * 2);
  const increment = () => count.value++;
  
  return { count, double, increment };
});

Pinia vs Vuex:

特性VuexPinia
语法选项式选项式 + Composition
TypeScript需额外配置原生支持
模块化namespaced自动模块化
体积较大更轻量
DevTools支持更好的支持
42. Vue Router 4 的变化?

答案要点:

  • 全面支持 Composition API
  • 新的导航守卫 API
  • 改进的路由匹配
// 组合式函数
import { useRoute, useRouter } from 'vue-router';

const route = useRoute();
const router = useRouter();

console.log(route.params.id);

const goToUser = () => {
  router.push({ name: 'user', params: { id: 1 } });
};

// 导航守卫(组件内)
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';

onBeforeRouteLeave((to, from) => {
  const answer = confirm('确定离开吗?');
  if (!answer) return false;
});
43. 如何优化 Vue3 应用性能?

答案要点:

  • 使用 v-once 渲染一次不更新的内容
  • 使用 v-memo 缓存条件渲染
  • 使用 shallowRef/shallowReactive 减少深层响应式开销
  • 异步组件 + Suspense
  • 虚拟列表处理大数据
  • 合理使用 computed 缓存计算

Nuxt 资料

🚀 基础概念

44. Nuxt 是什么?核心特性?

答案要点:

  • 基于 Vue 的全栈框架
  • 核心特性:
    • 服务端渲染(SSR/SSG/ISR)
    • 文件系统自动路由
    • 自动导入(Auto-imports)
    • 模块生态
    • SEO 优化
45. Nuxt 3 的渲染模式?
// nuxt.config.ts
export default defineNuxtConfig({
  // SSR 模式(默认)
  ssr: true,
  
  // 静态生成
  nitro: {
    prerender: {
      routes: ['/about', '/contact']
    }
  },
  
  // 混合模式
  routeRules: {
    '/admin/**': { ssr: false }, // 纯客户端
    '/blog/**': { isr: 60 }      // ISR
  }
});
46. Nuxt 的目录结构约定?
.nuxt/           # 构建输出(自动生成)
assets/          # 未编译资源(CSS、字体、图片)
components/      # Vue 组件(自动导入)
composables/     # 组合式函数(自动导入)
layouts/         # 布局组件
middleware/      # 中间件
pages/           # 页面路由(文件系统路由)
plugins/         # 插件
public/          # 静态文件
server/          # 服务端代码(API 路由、中间件)
stores/          # Pinia 状态(可选)
nuxt.config.ts   # 配置文件
47. 什么是 Auto-imports?

答案要点:

  • 自动导入组件、组合式函数、Vue API
  • 无需手动 import
<template>
  <!-- 组件自动导入 -->
  <MyComponent />
</template>

<script setup>
// Vue API 自动导入
const count = ref(0);
const double = computed(() => count.value * 2);

// 组合式函数自动导入(来自 composables/ 目录)
const user = useUser();

// Nuxt 内置组合式函数
const route = useRoute();
const router = useRouter();
const { data } = await useFetch('/api/data');
</script>
48. Nuxt 的数据获取方法?
<script setup>
// useFetch - 最常用
const { data, pending, error, refresh } = await useFetch('/api/users');

// useAsyncData - 更灵活的控制
const { data: posts } = await useAsyncData('posts', () => {
  return $fetch('/api/posts');
});

// 客户端获取
const fetchData = async () => {
  const data = await $fetch('/api/data');
};

// 带参数和选项
const { data } = await useFetch('/api/users', {
  query: { page: 1, limit: 10 },
  server: false,      // 只在客户端执行
  default: () => [],  // 默认值
  transform: (data) => data.map(transformUser)
});
</script>

🔧 进阶特性

49. Nuxt 服务端和客户端代码如何区分?
<script setup>
// 只在服务端执行
if (process.server) {
  console.log('Server only');
}

// 只在客户端执行
if (process.client) {
  console.log('Client only');
}

// 使用组合式函数
onMounted(() => {
  // 只在客户端执行
});

// 插件中
export default defineNuxtPlugin({
  name: 'my-plugin',
  enforce: 'pre', // 执行顺序
  async setup(nuxtApp) {
    // 插件逻辑
  }
});
</script>
50. Server API Routes 如何使用?
// server/api/users.get.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event);
  const users = await db.getUsers(query);
  return users;
});

// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  const user = await db.createUser(body);
  return user;
});

// server/routes/hello.ts(直接作为路由)
export default defineEventHandler(() => {
  return { message: 'Hello!' };
});

// server/middleware/auth.ts(中间件)
export default defineEventHandler((event) => {
  const token = getHeader(event, 'authorization');
  if (!token) {
    throw createError({ statusCode: 401, message: 'Unauthorized' });
  }
  event.context.user = verifyToken(token);
});
51. Nuxt 如何处理 SEO 和 Meta?
<script setup>
// 使用 useHead
useHead({
  title: '页面标题',
  meta: [
    { name: 'description', content: '页面描述' },
    { property: 'og:title', content: 'Open Graph 标题' }
  ],
  link: [
    { rel: 'canonical', href: 'https://example.com/page' }
  ]
});

// 使用 useSeoMeta(类型安全)
useSeoMeta({
  title: '页面标题',
  description: '页面描述',
  ogTitle: 'Open Graph 标题',
  ogDescription: 'Open Graph 描述',
  twitterCard: 'summary_large_image'
});

// 动态数据
const { data } = await useFetch('/api/post/1');
useHead({
  title: data.value?.title,
  meta: [
    { name: 'description', content: data.value?.description }
  ]
});
</script>
52. 什么是 Nuxt 模块(Modules)?

答案要点:

  • 扩展 Nuxt 功能的插件包
  • 常用模块:
    • @nuxtjs/tailwindcss - Tailwind CSS 集成
    • @nuxtjs/i18n - 国际化
    • @nuxtjs/seo - SEO 优化
    • @pinia/nuxt - 状态管理
// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/tailwindcss',
    '@pinia/nuxt',
    '@nuxtjs/i18n'
  ],
  i18n: {
    locales: ['en', 'zh'],
    defaultLocale: 'zh'
  }
});

Node.js 资料

🔧 核心基础

53. Node.js 是什么?特点?

答案要点:

  • 基于 Chrome V8 引擎的 JavaScript 运行时
  • 核心特点:
    • 事件驱动(Event-driven)
    • 非阻塞 I/O(Non-blocking I/O)
    • 单线程 + 事件循环
    • 跨平台
    • 丰富的 npm 生态
54. 事件循环(Event Loop)的工作原理?

答案要点:

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌──────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:  │
│  │           poll            │<─────┤  connections │
│  └─────────────┬─────────────┘      │   data, etc. │
│  ┌─────────────┴─────────────┐      └──────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

阶段说明:

  1. timers: 执行 setTimeout/setInterval 回调
  2. pending callbacks: 执行系统操作的回调
  3. idle/prepare: Node 内部使用
  4. poll: 检索新的 I/O 事件,执行 I/O 回调
  5. check: 执行 setImmediate 回调
  6. close callbacks: 执行 close 事件回调

执行顺序示例:

console.log('1'); // 同步

setTimeout(() => console.log('2'), 0); // 宏任务 - timers
setImmediate(() => console.log('3'));  // 宏任务 - check

Promise.resolve().then(() => console.log('4')); // 微任务

process.nextTick(() => console.log('5')); // nextTick

console.log('6'); // 同步

// 输出:1 → 6 → 5 → 4 → 2 → 3
55. 微任务和宏任务的区别?
特性微任务 (Microtask)宏任务 (Macrotask)
包含Promise.then, queueMicrotask, process.nextTicksetTimeout, setInterval, setImmediate, I/O
执行时机当前操作完成后,下一个宏任务前事件循环的特定阶段
优先级相对较低
56. CommonJS vs ES Modules?
特性CommonJS (CJS)ES Modules (ESM)
语法require/module.exportsimport/export
加载方式运行时同步加载编译时静态分析
加载时机运行时解析阶段
动态导入原生支持import() 函数
循环依赖部分支持更好支持
文件扩展名.js/.cjs.mjs / package.json "type": "module"
// CommonJS
const fs = require('fs');
module.exports = { foo: 'bar' };

// ES Modules
import fs from 'fs';
import { readFile } from 'fs/promises';
export const foo = 'bar';
export default mainFunction;

// 动态导入(ESM)
const module = await import('./module.js');
57. Buffer 是什么?

答案要点:

  • 用于处理二进制数据的类
  • 类似整数数组,但大小固定
  • 在 TCP 流、文件操作等场景使用
// 创建 Buffer
const buf1 = Buffer.alloc(10); // 分配 10 字节
const buf2 = Buffer.from('Hello'); // 从字符串创建
const buf3 = Buffer.from([1, 2, 3]); // 从数组创建

// 操作
buf2.toString(); // 'Hello'
Buffer.concat([buf1, buf2]); // 合并
58. Stream 是什么?类型?

答案要点:

  • 流是处理数据的一种方式,分块处理,节省内存
  • 四种类型:
    • Readable: 可读流(fs.createReadStream)
    • Writable: 可写流(fs.createWriteStream)
    • Duplex: 双工流(net.Socket)
    • Transform: 转换流(zlib.createGzip)
const fs = require('fs');
const zlib = require('zlib');

// 管道:读取 → 压缩 → 写入
fs.createReadStream('input.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('input.txt.gz'));

🌐 进阶特性

59. Cluster 模块是什么?

答案要点:

  • 创建多进程集群,利用多核 CPU
  • 主进程(Master)管理工作进程(Worker)
  • 工作进程共享服务器端口
const cluster = require('cluster');
const http = require('http');
const os = require('os');

if (cluster.isMaster) {
  // 启动多个工作进程
  const numCPUs = os.cpus().length;
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  // 工作进程创建 HTTP 服务器
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World');
  }).listen(8000);
}
60. 如何处理 Node.js 错误?

答案要点:

// 1. 同步错误 try-catch
try {
  riskyOperation();
} catch (error) {
  console.error('Error:', error);
}

// 2. 异步错误(回调)
fs.readFile('file.txt', (err, data) => {
  if (err) {
    console.error('Read error:', err);
    return;
  }
  // 处理 data
});

// 3. Promise 错误
doSomething()
  .then(result => process(result))
  .catch(error => console.error('Promise error:', error));

// 4. async/await
try {
  const result = await doSomething();
} catch (error) {
  console.error('Async error:', error);
}

// 5. 全局错误捕获
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection:', reason);
});
61. Node.js 如何调试?

答案要点:

# 1. 内置调试器
node inspect app.js
node --inspect app.js        # Chrome DevTools
node --inspect-brk app.js    # 首行断点

# 2. 使用 debugger 语句
function test() {
  debugger;  // 在此处断点
  console.log('test');
}

# 3. console 方法
console.log('Debug info');
console.table([{ name: 'John', age: 30 }]);
console.time('timer');
// ... 代码
console.timeEnd('timer');
62. 如何优化 Node.js 性能?

答案要点:

  • 使用 Cluster/Worker Threads 利用多核
  • 启用 HTTP Keep-Alive
  • 使用缓存(Redis/Memcached)
  • 数据库连接池
  • 使用 Stream 处理大文件
  • 使用 CDN 分发静态资源
  • 压缩响应(gzip/brotli)
  • APM 工具监控性能瓶颈

NestJS 资料

🏗️ 架构基础

63. NestJS 是什么?核心设计思想?

答案要点:

  • 用于构建高效、可扩展的 Node.js 服务端应用的框架
  • 核心设计思想:
    • 模块化架构(Modular)
    • 依赖注入(Dependency Injection)
    • 装饰器驱动的开发
    • 支持 TypeScript
    • 受 Angular 启发
64. 核心概念:Module、Controller、Provider
// 模块 (Module) - 组织应用的基本单元
@Module({
  imports: [OtherModule],           // 导入其他模块
  controllers: [UserController],    // 声明控制器
  providers: [UserService],         // 声明提供者(服务)
  exports: [UserService]            // 导出供其他模块使用
})
export class UserModule {}

// 控制器 (Controller) - 处理请求
@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}
  
  @Get()
  findAll() {
    return this.userService.findAll();
  }
  
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.userService.findOne(id);
  }
  
  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
}

// 提供者/服务 (Provider) - 业务逻辑
@Injectable()
export class UserService {
  private users = [];
  
  findAll() {
    return this.users;
  }
  
  findOne(id: string) {
    return this.users.find(user => user.id === id);
  }
  
  create(createUserDto: CreateUserDto) {
    const user = { id: Date.now().toString(), ...createUserDto };
    this.users.push(user);
    return user;
  }
}
65. 依赖注入(DI)是如何工作的?

答案要点:

  • IoC 容器: NestJS 内置控制反转容器
  • 注入方式:
    • 构造函数注入(推荐)
    • 属性注入
  • 作用域:
    • DEFAULT(单例)
    • REQUEST(每次请求新实例)
    • TRANSIENT(每次注入新实例)
// 构造函数注入
@Injectable()
export class UserService {
  constructor(
    private readonly httpService: HttpService,
    @Inject('DATABASE') private readonly db: Database,
    @Optional() private readonly cache?: CacheService
  ) {}
}

// 自定义 Provider
@Module({
  providers: [
    {
      provide: 'DATABASE',
      useValue: { host: 'localhost', port: 5432 }
    },
    {
      provide: UserService,
      useClass: MockUserService // 测试时替换实现
    },
    {
      provide: 'ASYNC_CONFIG',
      useFactory: async () => {
        return await loadConfig();
      }
    }
  ]
})
66. 装饰器汇总
// 模块装饰器
@Module({})
@Global()  // 全局模块

// 控制器装饰器
@Controller('path')
@Get() @Post() @Put() @Patch() @Delete() @Options() @Head() @All()

// 参数装饰器
@Param('id')         // URL 参数
@Query('search')     // 查询参数
@Body()             // 请求体
@Headers()          // 请求头
@Ip()               // 客户端 IP
@Req() @Res()       // 请求/响应对象

// 方法装饰器
@HttpCode(201)       // 设置状态码
@Header('X-Key', 'value')  // 设置响应头
@Redirect('/url', 301)     // 重定向

// 其他装饰器
@Injectable()        // 标记为可注入
@Catch()            // 异常过滤器
@UseGuards()        // 使用守卫
@UseInterceptors()  // 使用拦截器
@UsePipes()         // 使用管道

🛡️ 进阶特性

67. 管道(Pipe)是什么?常用管道?

答案要点:

  • 在控制器方法处理之前对输入数据进行转换和验证
  • 常用管道:
    • ValidationPipe - 数据验证
    • ParseIntPipe - 字符串转数字
    • ParseBoolPipe - 字符串转布尔
    • ParseArrayPipe - 解析数组
// 内置管道使用
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
  return this.service.findOne(id);
}

// 自定义管道
@Injectable()
export class ParseOptionalIntPipe implements PipeTransform {
  transform(value: string | undefined) {
    if (value === undefined) return undefined;
    const val = parseInt(value, 10);
    if (isNaN(val)) {
      throw new BadRequestException('Validation failed');
    }
    return val;
  }
}

// DTO 验证
import { IsString, IsEmail, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;
  
  @IsEmail()
  email: string;
}

// 全局启用验证
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,      // 去除未定义的属性
  forbidNonWhitelisted: true, // 拒绝未定义的属性
  transform: true       // 自动类型转换
}));
68. 守卫(Guard)和拦截器(Interceptor)的区别?
特性Guard(守卫)Interceptor(拦截器)
用途权限控制、认证数据转换、日志、缓存
执行时机控制器方法之前方法前后都可
返回值boolean 或 PromiseObservable 或修改后的数据
// Guard - 认证守卫
@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}
  
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization?.split(' ')[1];
    
    try {
      const payload = this.jwtService.verify(token);
      request.user = payload;
      return true;
    } catch {
      return false;
    }
  }
}

// 使用
@Controller('users')
@UseGuards(JwtAuthGuard)
export class UserController {}

// Interceptor - 转换响应
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
    return next.handle().pipe(
      map(data => ({
        data,
        code: 200,
        message: 'success',
        timestamp: new Date().toISOString()
      }))
    );
  }
}

// 日志拦截器
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const start = Date.now();
    return next.handle().pipe(
      tap(() => {
        console.log(`Request took ${Date.now() - start}ms`);
      })
    );
  }
}
69. 异常过滤器(Exception Filter)
// 全局异常过滤器
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    
    const status = exception instanceof HttpException
      ? exception.getStatus()
      : HttpStatus.INTERNAL_SERVER_ERROR;
    
    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: exception instanceof Error ? exception.message : 'Internal error'
    });
  }
}

// 特定异常过滤器
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    // 处理 HTTP 异常
  }
}

// 应用
app.useGlobalFilters(new AllExceptionsFilter());
70. 如何与数据库集成(TypeORM / Prisma)?

TypeORM 示例:

// user.entity.ts
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;
  
  @Column()
  name: string;
  
  @Column({ unique: true })
  email: string;
  
  @CreateDateColumn()
  createdAt: Date;
}

// user.service.ts
@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>
  ) {}
  
  findAll(): Promise<User[]> {
    return this.userRepository.find();
  }
  
  async create(createUserDto: CreateUserDto): Promise<User> {
    const user = this.userRepository.create(createUserDto);
    return this.userRepository.save(user);
  }
}

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'user',
      password: 'password',
      database: 'mydb',
      entities: [User],
      synchronize: true // 开发环境
    }),
    TypeOrmModule.forFeature([User])
  ]
})

Prisma 示例:

// prisma/schema.prisma
model User {
  id        String   @id @default(uuid())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
}

// user.service.ts
@Injectable()
export class UserService {
  constructor(private prisma: PrismaService) {}
  
  findAll() {
    return this.prisma.user.findMany();
  }
  
  create(data: CreateUserDto) {
    return this.prisma.user.create({ data });
  }
}
71. WebSocket 如何实现?
// 安装: npm i @nestjs/websockets @nestjs/platform-socket.io

// gateway
@WebSocketGateway({
  cors: { origin: '*' },
  namespace: 'events'
})
export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;
  
  handleConnection(client: Socket) {
    console.log(`Client connected: ${client.id}`);
  }
  
  handleDisconnect(client: Socket) {
    console.log(`Client disconnected: ${client.id}`);
  }
  
  // 接收消息
  @SubscribeMessage('message')
  handleMessage(@MessageBody() data: string): WsResponse<string> {
    return { event: 'message', data: `Echo: ${data}` };
  }
  
  // 广播消息
  @SubscribeMessage('broadcast')
  handleBroadcast(@MessageBody() data: any) {
    this.server.emit('broadcast', data);
  }
}
72. 微服务如何构建?
// 微服务传输方式:TCP、Redis、NATS、RabbitMQ、Kafka 等

// main.ts - 启动微服务
async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      transport: Transport.TCP,
      options: {
        host: 'localhost',
        port: 3001
      }
    }
  );
  await app.listen();
}

// 控制器
@Controller()
export class MathController {
  @MessagePattern({ cmd: 'sum' })  // 处理消息模式
  async sum(data: number[]): Promise<number> {
    return data.reduce((a, b) => a + b, 0);
  }
  
  @EventPattern('user_created')  // 处理事件
  async handleUserCreated(data: Record<string, unknown>) {
    console.log('User created:', data);
  }
}

// 客户端调用
@Injectable()
export class MathService {
  @Client({
    transport: Transport.TCP,
    options: { host: 'localhost', port: 3001 }
  })
  private client: ClientTCP;
  
  async calculateSum(numbers: number[]) {
    return this.client.send({ cmd: 'sum' }, numbers).toPromise();
  }
}

综合面试技巧

💡 面试准备建议

技术深度 vs 广度
职级重点
初级基础概念、API 使用、简单原理
中级源码理解、性能优化、工程化
高级架构设计、技术选型、团队管理
常见问题类型
  1. 概念题 - 是什么、有什么区别
  2. 原理题 - 底层实现、源码分析
  3. 实践题 - 怎么做、最佳实践
  4. 场景题 - 遇到问题怎么解决
回答技巧
  • STAR 法则: Situation(场景)→ Task(任务)→ Action(行动)→ Result(结果)
  • 结构化回答: 先总述,再分点,最后总结
  • 举例说明: 结合实际项目经验
项目介绍要点
1. 项目背景和目标
2. 技术栈选型理由
3. 你的职责和贡献
4. 遇到的技术难点及解决方案
5. 项目成果(数据指标)
反问环节建议
  • 团队技术栈和架构
  • 日常工作流程和协作方式
  • 技术挑战和学习机会
  • 代码审查和发布流程

📚 学习资源推荐

官方文档

源码学习

  • React Fiber 架构
  • Vue3 响应式系统
  • Node.js 事件循环实现

练习平台

  • LeetCode(算法)
  • Frontend Masters(系统课程)
  • Egghead.io(短视频教程)