成都前端面试复习文档 2025
基于 2025 年成都软件行业行情整理,涵盖高频面试考点
📊 成都前端市场分析
当前行情概况
薪资水平(2025年):
- 应届生/实习生:6-8K
- 1-2年经验:8-12K
- 3-5年经验:12-20K
- 5年以上:20K+
主要分布区域:
- 高新区(天府软件园、天府N街)
- 武侯区
- 双流区
主流技术栈:
- Vue3 + TypeScript + Vite
- React18 + TypeScript + Next.js
- Node.js 基础
- 工程化工具(Webpack、Vite)
企业类型:
- 互联网公司(字节跳动、腾讯、阿里等)
- 金融科技公司
- 游戏公司
- 政务/企业级应用公司
📚 目录
JavaScript 核心
1. 数据类型与判断
基本数据类型(7种):
- String、Number、Boolean、Null、Undefined、Symbol、BigInt
引用数据类型:
- Object(Array、Function、Date、RegExp、Map、Set 等)
类型判断方法:
// typeof - 判断基本类型
typeof undefined // 'undefined'
typeof null // 'object' (历史遗留问题)
typeof [] // 'object'
typeof {} // 'object'
// instanceof - 判断引用类型
[] instanceof Array // true
{} instanceof Object // true
new Date() instanceof Date // true
// Object.prototype.toString - 最准确
const getType = (val) => Object.prototype.toString.call(val).slice(8, -1);
getType([]) // 'Array'
getType({}) // 'Object'
getType(null) // 'Null'
getType(undefined) // 'Undefined'
面试题:
// 判断数组的方法
Array.isArray([]) // true
Array.isArray({}) // false
// 深拷贝实现
function deepClone(obj, map = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (map.has(obj)) return map.get(obj); // 处理循环引用
const clone = Array.isArray(obj) ? [] : {};
map.set(obj, clone);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], map);
}
}
return clone;
}
2. this 指向问题
this 的 6 种指向:
| 场景 | this 指向 |
|---|---|
| 全局环境 | window |
| 普通函数 | window |
| 对象方法 | 对象本身 |
| 事件处理函数 | 事件源 |
| 构造函数 | 实例对象 |
| 箭头函数 | 继承外层 this |
修改 this 指向:
// call - 立即调用,参数逐个传递
fn.call(obj, arg1, arg2);
// apply - 立即调用,参数数组传递
fn.apply(obj, [arg1, arg2]);
// bind - 返回新函数
const boundFn = fn.bind(obj);
boundFn(arg1, arg2);
面试题:
// 经典面试题
var name = 'global';
const obj = {
name: 'obj',
getName: function() {
return this.name;
}
};
console.log(obj.getName()); // 'obj'
const fn = obj.getName;
console.log(fn()); // 'global'
console.log(obj.getName.call({ name: 'new' })); // 'new'
// 箭头函数
const obj2 = {
name: 'obj2',
getName: () => {
return this.name; // 继承外层 this
}
};
console.log(obj2.getName()); // 'undefined' (严格模式) 或 'global'
3. 闭包与作用域
闭包定义: 函数内部定义函数,内部函数引用外部函数的变量,形成闭包。
闭包作用:
- 延长变量生命周期
- 创建私有变量
- 模块化
面试题:
// 经典闭包面试题
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i); // 5 5 5 5 5
}, 100);
}
// 解决方案一:let
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i); // 0 1 2 3 4
}, 100);
}
// 解决方案二:闭包
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(() => {
console.log(i); // 0 1 2 3 4
}, 100);
})(i);
}
// 解决方案三:bind
for (var i = 0; i < 5; i++) {
setTimeout(function(i) {
console.log(i); // 0 1 2 3 4
}.bind(null, i), 100);
}
4. 原型与原型链
核心概念:
function Person(name) {
this.name = name;
}
Person.prototype.sayName() {
console.log(this.name);
}
const person = new Person('Tom');
// 原型链关系
person.__proto__ === Person.prototype // true
Person.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true
// instanceof 原理
person instanceof Person // true
person instanceof Object // true
继承方式:
// 1. 原型链继承
function Child() {}
Child.prototype = new Parent();
// 2. 构造函数继承
function Child() {
Parent.call(this);
}
// 3. 组合继承
function Child() {
Parent.call(this);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
// 4. ES6 class 继承(推荐)
class Child extends Parent {
constructor() {
super();
}
}
5. 事件循环(Event Loop)
宏任务:
- setTimeout、setInterval
- I/O 操作
- UI 渲染
- setImmediate(Node.js)
微任务:
- Promise.then/catch/finally
- process.nextTick(Node.js)
- MutationObserver
- queueMicrotask
执行顺序:
- 执行同步代码
- 执行所有微任务
- 执行一个宏任务
- 重复步骤 2-3
经典面试题:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
Promise.resolve().then(() => {
console.log('4');
setTimeout(() => console.log('5'), 0);
});
console.log('6');
// 输出:1 6 3 4 2 5
复杂面试题:
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => console.log('setTimeout'), 0);
async1();
new Promise(resolve => {
console.log('promise1');
resolve();
}).then(() => console.log('promise2'));
console.log('script end');
// 输出:
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// setTimeout
6. 异步编程
Promise 核心方法:
// Promise.all - 所有成功才成功
Promise.all([p1, p2, p3])
.then(results => console.log(results))
.catch(error => console.log(error));
// Promise.race - 谁快用谁
Promise.race([p1, p2, p3])
.then(result => console.log(result));
// Promise.allSettled - 返回所有结果
Promise.allSettled([p1, p2, p3])
.then(results => console.log(results));
// Promise.any - 只要有一个成功就成功
Promise.any([p1, p2, p3])
.then(result => console.log(result));
async/await 错误处理:
// 方式一:try-catch
async function fetchData() {
try {
const data = await fetch('/api/data');
return await data.json();
} catch (error) {
console.error(error);
throw error;
}
}
// 方式二:.catch()
async function fetchData() {
const data = await fetch('/api/data')
.catch(error => {
console.error(error);
throw error;
});
return await data.json();
}
TypeScript(必考)
⚠️ 成都市场现状:TypeScript 已成为标配,不会 TS 很难找到好工作
1. 基础类型
// 基本类型
let name: string = 'Tom';
let age: number = 18;
let isStudent: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;
// 数组
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ['a', 'b', 'c'];
// 元组
let tuple: [string, number] = ['Tom', 18];
// 枚举
enum Color {
Red,
Green,
Blue
}
let color: Color = Color.Red;
// any 和 unknown
let anything: any = 10;
let unknownValue: unknown = 10;
// void
function log(message: string): void {
console.log(message);
}
// never
function error(message: string): never {
throw new Error(message);
}
2. 接口与类型别名
// 接口
interface Person {
name: string;
age: number;
sayHello(): void;
}
// 类型别名
type PersonType = {
name: string;
age: number;
};
// 可选属性
interface User {
id: number;
name: string;
age?: number; // 可选
}
// 只读属性
interface Config {
readonly id: number;
name: string;
}
// 函数类型
type AddFunction = (a: number, b: number) => number;
const add: AddFunction = (a, b) => a + b;
3. 泛型
// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 泛型接口
interface Box<T> {
value: T;
}
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
4. 类型推断与类型守卫
// 类型推断
let x = 3; // 推断为 number
// 类型守卫 - typeof
function printId(id: string | number) {
if (typeof id === 'string') {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
// 类型守卫 - instanceof
class Bird {
fly() {}
}
class Fish {
swim() {}
}
function move(animal: Bird | Fish) {
if (animal instanceof Bird) {
animal.fly();
} else {
animal.swim();
}
}
// 类型守卫 - in
interface Square {
kind: 'square';
size: number;
}
interface Circle {
kind: 'circle';
radius: number;
}
function getArea(shape: Square | Circle) {
if (shape.kind === 'square') {
return shape.size * shape.size;
} else {
return Math.PI * shape.radius * shape.radius;
}
}
5. 高级类型
// 联合类型
type ID = string | number;
// 交叉类型
type Person = {
name: string;
};
type Employee = {
id: number;
};
type PersonEmployee = Person & Employee;
// 条件类型
type NonNullable<T> = T extends null | undefined ? never : T;
// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 索引签名
interface StringDictionary {
[index: string]: string;
}
6. 装饰器
// 类装饰器
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {}
// 方法装饰器
function log(target: MethodDecoratorContext, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyKey} with`, args);
return originalMethod.apply(this, args);
};
}
class Calculator {
@log
add(a: number, b: number) {
return a + b;
}
}
Vue3 全家桶
1. Vue3 核心特性
Composition API vs Options API:
| 特性 | Options API | Composition API |
|---|---|---|
| 代码组织 | 按选项分类 | 按功能组织 |
| 逻辑复用 | Mixins | Composables |
| TypeScript 支持 | 较弱 | 强 |
| this | 依赖 this | 无 this |
响应式原理:
// Vue2 - Object.defineProperty
Object.defineProperty(obj, 'key', {
get() {
// 收集依赖
},
set(newVal) {
// 触发更新
}
});
// Vue3 - Proxy
const proxy = new Proxy(target, {
get(target, key) {
// 收集依赖
return Reflect.get(target, key);
},
set(target, key, value) {
// 触发更新
return Reflect.set(target, key, value);
}
});
2. Composition API
ref vs reactive:
import { ref, reactive } from 'vue';
// ref - 用于基本类型
const count = ref(0);
console.log(count.value); // 访问需要 .value
// reactive - 用于对象
const state = reactive({
name: 'Tom',
age: 18
});
console.log(state.name); // 直接访问
// toRefs - 解构 reactive
const { name, age } = toRefs(state);
computed 和 watch:
import { ref, computed, watch, watchEffect } from 'vue';
const count = ref(0);
// computed - 计算属性
const doubled = computed(() => count.value * 2);
// watch - 监听
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`);
});
// watchEffect - 自动追踪依赖
watchEffect(() => {
console.log(`count is ${count.value}`);
});
生命周期:
import { onMounted, onUpdated, onUnmounted } from 'vue';
onMounted(() => {
console.log('组件已挂载');
});
onUpdated(() => {
console.log('组件已更新');
});
onUnmounted(() => {
console.log('组件已卸载');
});
3. 组件通信
父传子(props):
<!-- 父组件 -->
<template>
<Child :message="parentMessage" :count="count" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import Child from './Child.vue';
const parentMessage = ref('Hello from parent');
const count = ref(0);
</script>
<!-- 子组件 -->
<script setup lang="ts">
interface Props {
message: string;
count?: number;
}
const props = withDefaults(defineProps<Props>(), {
count: 0
});
</script>
子传父(emit):
<!-- 子组件 -->
<script setup lang="ts">
const emit = defineEmits<{
(e: 'update', value: number): void;
(e: 'delete', id: number): void;
}>();
const handleClick = () => {
emit('update', 10);
};
</script>
<!-- 父组件 -->
<template>
<Child @update="handleUpdate" />
</template>
<script setup lang="ts">
const handleUpdate = (value: number) => {
console.log('Received:', value);
};
</script>
provide/inject(跨层级):
// 祖先组件
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
// 后代组件
import { inject } from 'vue';
const theme = inject('theme');
4. Vue Router
路由模式:
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router';
// history 模式(需要服务器配置)
const router = createRouter({
history: createWebHistory(),
routes: []
});
// hash 模式
const router = createRouter({
history: createWebHashHistory(),
routes: []
});
路由守卫:
// 全局前置守卫
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
// 路由独享守卫
{
path: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
if (isAdmin()) {
next();
} else {
next('/403');
}
}
}
5. Pinia(状态管理)
定义 Store:
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
name: '',
age: 0
}),
getters: {
doubleAge: (state) => state.age * 2
},
actions: {
async fetchUser() {
const data = await api.getUser();
this.name = data.name;
this.age = data.age;
}
}
});
使用 Store:
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
// 访问 state
console.log(userStore.name);
// 访问 getters
console.log(userStore.doubleAge);
// 调用 actions
userStore.fetchUser();
6. 性能优化
v-if vs v-show:
| 特性 | v-if | v-show |
|---|---|---|
| 渲染 | 条件为 false 不渲染 | 始终渲染 |
| 切换开销 | 高(销毁/重建) | 低(display 切换) |
| 初始开销 | 低 | 高 |
key 的作用:
<!-- 正确:使用唯一 key -->
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
<!-- 错误:使用 index -->
<li v-for="(item, index) in list" :key="index">{{ item.name }}</li>
keep-alive:
<template>
<keep-alive include="ComponentA,ComponentB">
<component :is="currentComponent" />
</keep-alive>
</template>
React 生态
1. React Hooks
useState:
const [count, setCount] = useState(0);
// 函数式更新
setCount(prev => prev + 1);
useEffect:
useEffect(() => {
// 副作用
document.title = `Count: ${count}`;
// 清理函数
return () => {
console.log('cleanup');
};
}, [count]); // 依赖项
useContext:
const ThemeContext = createContext('light');
// 提供者
<ThemeContext.Provider value="dark">
<App />
</ThemeContext.Provider>
// 消费者
const theme = useContext(ThemeContext);
useMemo 和 useCallback:
// useMemo - 缓存值
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
// useCallback - 缓存函数
const memoizedCallback = useCallback(
() => doSomething(a, b),
[a, b]
);
useRef:
const inputRef = useRef<HTMLInputElement>(null);
// 访问 DOM
inputRef.current?.focus();
// 保存可变值
const timerRef = useRef<number>();
timerRef.current = window.setTimeout(() => {}, 1000);
2. React 性能优化
React.memo:
const MemoizedComponent = React.memo<Props>(function MyComponent(props) {
return <div>{props.value}</div>;
}, (prevProps, nextProps) => {
// 自定义比较函数
return prevProps.value === nextProps.value;
});
useMemo 和 useCallback 的使用场景:
// useMemo - 计算属性
const expensiveValue = useMemo(() => {
return bigArray.filter(item => item.active).map(item => item.value * 2);
}, [bigArray]);
// useCallback - 传递给子组件的函数
const handleClick = useCallback((id: number) => {
setSelectedId(id);
}, []);
虚拟列表:
import { FixedSizeList } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const VirtualList = () => (
<FixedSizeList
height={600}
itemCount={10000}
itemSize={50}
width={300}
>
{Row}
</FixedSizeList>
);
3. React Router
路由配置:
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{ path: 'about', element: <About /> }
]
}
]);
function App() {
return <RouterProvider router={router} />;
}
路由守卫:
const ProtectedRoute = ({ children }) => {
if (!isAuthenticated()) {
return <Navigate to="/login" replace />;
}
return children;
};
4. Redux Toolkit
创建 Slice:
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
}
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
配置 Store:
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer
}
});
性能优化
1. 网络优化
减少 HTTP 请求:
- 合并 CSS 和 JS 文件
- 使用雪碧图(CSS Sprites)
- 使用 Base64 编码小图片
使用 CDN:
- 静态资源使用 CDN 加速
- 多节点部署,就近访问
开启 Gzip 压缩:
// Vite 配置
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
viteCompression({
algorithm: 'gzip',
ext: '.gz'
})
]
});
HTTP/2:
- 多路复用
- 头部压缩
- 服务器推送
2. 资源优化
图片优化:
- 使用 WebP 格式
- 图片懒加载
- 响应式图片
// 图片懒加载
<img loading="lazy" src="image.jpg" alt="description" />
代码分割:
// 动态导入
const LazyComponent = lazy(() => import('./LazyComponent'));
// 路由级别代码分割
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
Tree Shaking:
- 移除未使用的代码
- 使用 ES6 模块语法
3. 渲染优化
减少重排和重绘:
// 批量 DOM 操作
const fragment = document.createDocumentFragment();
items.forEach(item => {
const li = document.createElement('li');
li.textContent = item;
fragment.appendChild(li);
});
ul.appendChild(fragment);
使用 requestAnimationFrame:
function animate() {
// 动画逻辑
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
防抖和节流:
// 防抖
function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timer: NodeJS.Timeout;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
// 节流
function throttle<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime > delay) {
fn(...args);
lastTime = now;
}
};
}
4. 缓存优化
强缓存:
// Cache-Control: max-age=31536000
协商缓存:
// ETag
// Last-Modified
LocalStorage:
// 设置
localStorage.setItem('key', JSON.stringify(value));
// 获取
const value = JSON.parse(localStorage.getItem('key') || 'null');
// 删除
localStorage.removeItem('key');
SessionStorage:
- 会话级别存储
- 关闭标签页后清除
IndexedDB:
- 大量数据存储
- 异步操作
- 支持索引查询
工程化与构建
1. Vite(推荐)
Vite vs Webpack:
| 特性 | Vite | Webpack |
|---|---|---|
| 启动速度 | 快(ESM) | 慢(打包) |
| HMR | 极快 | 较慢 |
| 配置 | 简单 | 复杂 |
| 生态 | 新兴 | 成熟 |
Vite 配置:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
build: {
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia']
}
}
}
}
});
2. Webpack
核心概念:
- Entry:入口
- Output:输出
- Loader:转换器
- Plugin:插件
- Mode:模式
常用 Loader:
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.ts$/,
loader: 'ts-loader'
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.(png|jpg|gif)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb
}
}
}
]
}
常用 Plugin:
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'
}),
new CleanWebpackPlugin()
]
3. ESLint 和 Prettier
ESLint 配置:
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser'
}
};
Prettier 配置:
module.exports = {
semi: false,
singleQuote: true,
trailingComma: 'none',
printWidth: 100
};
网络与安全
1. HTTP 状态码
2xx 成功:
- 200 OK
- 201 Created
- 204 No Content
3xx 重定向:
- 301 Moved Permanently
- 302 Found
- 304 Not Modified
4xx 客户端错误:
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
5xx 服务器端错误:
- 500 Internal Server Error
- 502 Bad Gateway
- 503 Service Unavailable
2. 跨域问题
CORS(推荐):
// 服务器端设置
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
JSONP(只支持 GET):
function jsonp(url, callbackName) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = `${url}?callback=${callbackName}`;
window[callbackName] = (data) => {
resolve(data);
delete window[callbackName];
document.body.removeChild(script);
};
document.body.appendChild(script);
});
}
3. 前端安全
XSS(跨站脚本攻击):
// 防御:转义特殊字符
function escapeHtml(unsafe: string): string {
return unsafe
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
CSRF(跨站请求伪造):
// 防御:使用 CSRF Token
// 1. 服务器生成 Token
// 2. 客户端请求时携带 Token
// 3. 服务器验证 Token
内容安全策略(CSP):
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'">
Node.js
1. CommonJS vs ES Modules
CommonJS:
// 导出
module.exports = {
name: 'module'
};
// 或
exports.name = 'module';
// 导入
const module = require('./module');
ES Modules:
// 导出
export const name = 'module';
export default function() {}
// 导入
import module, { name } from './' + 'module';
2. 内置模块
fs 模块:
import fs from 'fs/promises';
// 异步读取
const data = await fs.readFile('./file.txt', 'utf8');
// 异步写入
await fs.writeFile('./file.txt', 'content');
// 检查文件是否存在
const exists = await fs.access('./file.txt').then(() => true).catch(() => false);
http 模块:
import http from 'http';
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello World' }));
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
path 模块:
import path from 'path';
path.join('/foo', 'bar', 'baz'); // '/foo/bar/baz'
path.resolve('/foo/bar', './baz'); // '/foo/bar/baz'
path.basename('/foo/bar/baz.txt'); // 'baz.txt'
3. 事件驱动
import { EventEmitter } from 'events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (data) => {
console.log('Event received:', data);
});
myEmitter.emit('event', { message: 'Hello' });
算法与数据结构
1. 数组操作
数组去重:
// 方法一:Set
const unique = [...new Set(array)];
// 方法二:filter + indexOf
const unique = array.filter((item, index) => array.indexOf(item) === index);
// 方法三:reduce
const unique = array.reduce((acc, cur) => {
return acc.includes(cur) ? acc : [...acc, cur];
}, []);
数组扁平化:
// 方法一:flat
const flattened = arr.flat(Infinity);
// 方法二:reduce
const flatten = (arr) => {
return arr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) ? flatten(cur) : cur);
}, []);
};
2. 常用算法
二分查找:
function binarySearch(arr: number[], target: number): number {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
快速排序:
function quickSort(arr: number[]): number[] {
if (arr.length <= 1) return arr;
const pivot = arr[0];
const left = arr.slice(1).filter(x => x <= pivot);
const right = arr.slice(1).filter(x => x > pivot);
return [...quickSort(left), pivot, ...quickSort(right)];
}
防抖和节流:
// 防抖
function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timer: NodeJS.Timeout;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
// 节流
function throttle<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime > delay) {
fn(...args);
lastTime = now;
}
};
}
项目实战问题
1. Vue3 项目问题
Q: Vue3 中 ref 和 reactive 的区别?
A:
ref用于基本类型,访问需要.valuereactive用于对象,直接访问ref在模板中自动解包,reactive不会
Q: Vue3 如何实现组件通信?
A:
- 父子:props + emit
- 跨层级:provide/inject
- 兄弟:事件总线或 Pinia
- 跨组件:Pinia
Q: Vue3 性能优化有哪些方法?
A:
- 使用
v-show替代频繁切换的v-if - 合理使用
key - 使用
keep-alive缓存组件 - 使用
computed缓存计算结果 - 按需引入组件
- 使用虚拟列表处理长列表
2. React 项目问题
Q: React Hooks 的使用规则?
A:
- 只在函数组件或自定义 Hook 中使用
- 只在顶层调用,不要在循环、条件或嵌套函数中调用
- 依赖项要正确填写
Q: React 如何避免不必要的渲染?
A:
- 使用
React.memo包裹组件 - 使用
useMemo缓存计算结果 - 使用
useCallback缓存函数 - 使用
key帮助 React 识别元素
Q: React 虚拟 DOM 的原理?
A:
- 用 JS 对象描述 DOM 结构
- 通过 Diff 算法比较新旧虚拟 DOM
- 只更新变化的部分
3. 工程化问题
Q: Vite 为什么比 Webpack 快?
A:
- Vite 使用原生 ESM,无需打包
- Webpack 需要先打包再启动
- Vite 的 HMR 是按需更新
Q: 如何优化构建速度?
A:
- 使用多线程(thread-loader)
- 缓存 loader 结果
- 减少构建文件数量
- 使用 DLL Plugin
Q: 如何优化打包体积?
A:
- Tree Shaking
- 代码分割
- 压缩代码
- 使用 CDN 引入大库
- 开启 Gzip
4. 性能优化问题
Q: 如何检测性能问题?
A:
- 使用 Chrome DevTools Performance
- 使用 Lighthouse
- 使用 WebPageTest
Q: 首屏加载优化有哪些方法?
A:
- 减少 HTTP 请求
- 使用 CDN
- 开启 Gzip
- 懒加载
- 预加载关键资源
- SSR(服务端渲染)
Q: 如何优化长列表渲染?
A:
- 使用虚拟列表
- 分页加载
- 无限滚动
面试技巧
1. 自我介绍
模板:
您好,我是[姓名],有[X]年前端开发经验。
技术栈方面:
- 熟练掌握 Vue3/React + TypeScript
- 熟悉 Node.js 和工程化工具
- 有性能优化和项目架构经验
项目经验:
- 参与过[项目类型]项目开发
- 负责[具体职责]
- 取得了[成果]
期望:
- 希望加入贵公司,共同成长
2. 回答技巧
STAR 原则:
- Situation(情境)
- Task(任务)
- Action(行动)
- Result(结果)
示例:
S: 在上一个项目中,我们遇到了首屏加载慢的问题
T: 我负责优化了首屏加载速度
A: 我使用了代码分割、懒加载、CDN 等技术
R: 首屏加载时间从 3s 降低到 1.5s
3. 常见问题
Q: 你遇到过什么技术难题?如何解决的?
A: 描述具体问题、解决思路、最终结果
Q: 你如何学习新技术?
A: 官方文档、技术博客、实践项目、技术分享
Q: 你的职业规划是什么?
A: 短期目标、长期目标、学习计划
复习计划
第 1 周:JavaScript 核心
- 数据类型与判断
- this 指向
- 闭包与作用域
- 原型与原型链
- 事件循环
- 异步编程
第 2 周:TypeScript
- 基础类型
- 接口与类型别名
- 泛型
- 类型推断与守卫
- 高级类型
- 装饰器
第 3 周:Vue3 全家桶
- Composition API
- 组件通信
- Vue Router
- Pinia
- 性能优化
第 4 周:React 生态
- React Hooks
- 性能优化
- React Router
- Redux Toolkit
第 5 周:工程化与性能优化
- Vite/Webpack
- 网络优化
- 渲染优化
- 缓存优化
第 6 周:项目实战与算法
- 项目问题总结
- 常用算法
- 面试技巧
- 模拟面试
总结
成都前端市场特点
- 技术栈要求高:Vue3/React + TypeScript 是标配
- 薪资水平:3-5年经验 12-20K
- 主要区域:高新区、武侯区
- 企业类型:互联网、金融科技、游戏、政务
高频考点
- JavaScript 核心:闭包、原型链、事件循环
- TypeScript:泛型、类型守卫、高级类型
- Vue3:Composition API、组件通信、性能优化
- React:Hooks、性能优化、虚拟 DOM
- 性能优化:网络、渲染、缓存优化
- 工程化:Vite、Webpack、代码分割
复习建议
- 理解原理:不要死记硬背
- 动手实践:多写代码
- 项目总结:梳理项目经验
- 模拟面试:练习表达
- 关注趋势:了解最新技术
祝你面试顺利,拿到心仪的 offer! 💪
成都市场机会很多,加油!技术过硬才是硬道理! 🚀