前端面试之设计模式怎么学

前端主学的还是计算机网络 然后就是设计模式
我在前端大厂校招过程的一些三面
是由部门负责人来面 但他不是前端
可能会从设计模式来考察你的编码功底(我经历过两次)
本文是对这些内容的分享 大家可以看看。

---
一、前端常用设计模式实战
1. 单例模式(Singleton)
场景:全局状态管理、浏览器环境唯一对象
示例:实现一个浏览器日志管理器
class Logger {
  constructor() {
    if (!Logger.instance) {
      this.logs = [];
      Logger.instance = this;
    }
    return Logger.instance;
  }

  log(message) {
    this.logs.push(message);
    console.log(`[LOG]: ${message}`);
  }
}

// 使用示例
const logger1 = new Logger();
const logger2 = new Logger();
console.log(logger1 === logger2); // true
框架应用:React Hooks 的 useState 内部通过单例模式管理状态队列
2. 装饰器模式(Decorator)
场景:功能扩展、高阶组件
示例:React 高阶组件增强
function withLoading(WrappedComponent) {
  return function EnhancedComponent(props) {
    const [loading, setLoading] = useState(true);
    
    useEffect(() => {
      props.fetchData().finally(() => setLoading(false));
    }, []);

    return loading ? <Spinner /> : <WrappedComponent {...props} />;
  };
}

// 使用
const EnhancedUserList = withLoading(UserList);
框架应用:Redux 的 connect 函数实现组件与 Store 的连接
3. 代理模式(Proxy)
场景:数据校验、缓存、对象访问控制
示例:API请求缓存代理
const apiService = {
  fetchData() {
    return axios.get('/api/data');
  }
};

const cachedApiProxy = new Proxy(apiService, {
  cache: new Map(),
  get(target, prop) {
    return (...args) => {
      const key = `${prop}-${JSON.stringify(args)}`;
      if (this.cache.has(key)) {
        return Promise.resolve(this.cache.get(key));
      }
      return target[prop](...args).then(res => {
        this.cache.set(key, res.data);
        return res.data;
      });
    };
  }
});

// 使用:重复调用会直接返回缓存
cachedApiProxy.fetchData().then(console.log);
框架应用:Vue3 的响应式系统基于 Proxy 实现数据劫持

---
二、发布订阅 vs 观察者模式深度解析
4. 核心差异
暂时无法在飞书文档外展示此内容
5. 代码实现对比
观察者模式:
class Subject {
  constructor() {
    this.observers = [];
  }
  addObserver(obs) {
    this.observers.push(obs);
  }
  notify(data) {
    this.observers.forEach(obs => obs.update(data));
  }
}

class Observer {
  update(data) {
    console.log('Received:', data);
  }
}
发布订阅模式:
class EventBus {
  constructor() {
    this.events = new Map();
  }
  
  on(event, callback) {
    const handlers = this.events.get(event) || [];
    handlers.push(callback);
    this.events.set(event, handlers);
  }
  
  emit(event, ...args) {
    const handlers = this.events.get(event);
    handlers?.forEach(handler => handler(...args));
  }
}
6. 实际应用场景
- 观察者模式:Vue 的 watch 实现、React Class 组件的生命周期通知
- 发布订阅:跨组件通信(Vue EventBus)、Redux 的 subscribe 机制、WebSocket 消息处理

---
三、框架源码中的设计模式实践
7. React 中的组合模式
- 组件嵌套:通过 props.children 实现容器组件与展示组件解耦
- Hooks 组合:自定义 Hook 整合多个基础 Hook 的功能
function useUser() {
  const [user, setUser] = useState(null);
  useEffect(() => { /* 获取用户数据 */ }, []);
  return user;
}

// 组合多个自定义 Hook
function useUserProfile() {
  const user = useUser();
  const posts = usePosts(user?.id);
  return { user, posts };
}
8. Vue 的职责链模式
- 生命周期钩子:通过职责链传递处理控制权
- Vue Router 导航守卫:
router.beforeEach((to, from, next) => {
  // 身份验证链
  if (requiresAuth(to) && !isAuthenticated()) {
    next('/login');
  } else {
    next();
  }
});
9. Axios 的拦截器(责任链模式)
// 请求处理链
axios.interceptors.request.use(config => {
  config.headers.Authorization = getToken();
  return config;
});

// 响应处理链
axios.interceptors.response.use(
  response => response.data,
  error => handleError(error)
);
10. Koa 中间件机制(洋葱圈模型)
// 中间件责任链
app.use(async (ctx, next) => {
  console.log('Enter 1');
  await next(); // 传递控制权
  console.log('Exit 1');
});

app.use(async (ctx, next) => {
  console.log('Enter 2');
  await next();
  console.log('Exit 2');
});
// 执行顺序:Enter1 → Enter2 → Exit2 → Exit1

---
四、设计模式的选择策略
1. 复杂度控制:
  - 简单场景:优先使用函数式编程
  - 复杂交互:采用观察者/发布订阅模式解耦
  - 全局状态:单例模式 + 状态管理库
2. 性能权衡:
  - 代理模式会增加内存开销
  - 发布订阅模式需注意事件泄露问题
3. 框架适配:
  - React 生态:多使用组合模式、装饰器模式(HOC)
  - Vue 生态:善用观察者模式(响应式系统)

---
五、从源码中学习设计模式
案例:React Reconciler 的策略模式
React 的渲染器通过策略模式支持多平台:
// ReactDOM 的 HostConfig 策略对象
const DOMHostConfig = {
  createInstance(type, props) {
    return document.createElement(type);
  },
  appendChild(parent, child) {
    parent.appendChild(child);
  },
  // ...其他DOM操作方法
};

// React Native 实现不同策略
const NativeHostConfig = {
  createInstance(type, props) {
    return NativeModules.createView(type, props);
  }
};
案例:Vue 的工厂模式
Vue 组件实例化过程:
// 组件工厂函数
function createComponent(Ctor, props, context) {
  if (isObject(Ctor)) {
    Ctor = Vue.extend(Ctor);
  }
  const instance = new Ctor({
    propsData: props,
    parent: context
  });
  return instance;
}
其实一些框架、库的源码不懂设计模式就挺难看懂

 #想实习转正,又想准备秋招,我该怎么办#  gcHvJOf81ZPFAXKf0EfCaVPnbVJyczWt.jpg
#现在前端的就业环境真的很差吗#
全部评论
点赞 回复 分享
发布于 03-05 18:29 湖南

相关推荐

咦哟,从去年八月份开始长跑,两处实习转正都失败了,风雨飘摇,终于拿到offer了更新一下面试记录:秋招:多部门反复面试然后挂掉然后复活,具体问了啥已经忘了,只是被反复煎炸,直至焦香😋春招:base北京抖音hr打来电话说再次复活,准备面试,gogogo北京抖音一面:六道笔试题:1.promise顺序2.定义域问题3.flat展开4.并发请求5.岛屿数量算法(力扣)深度,广度都写6.忘记了,好像也是算法,难度中等其他问题多是框架底层设计,实习项目重难点~~~秒过😇北京抖音二面:三道笔试题:(为什么只有三道是因为第三道没做出来,卡住了)1.中等难度算法(忘记啥题了,应该是个数组的)2.认识js的继承本质(手写继承模式,深入js的面相对象开发)3.手写vue的响应式(卡在了watch,导致挂掉)---后知后觉是我的注册副作用函数写得有问题,有点紧张了其他题目多是项目拷打,项目亮点,对实习项目的贡献~~~第二天,挂,but立马复活转战深圳客服当天约面深圳客服一面:六道笔试题,由于面过太多次字节,面试官叫我直接写,不用讲,快些写完😋,具体都是些继承,深拷贝(注意对数组对象分开处理,深层次对象,循环引用),加中等难度算法题~~~秒过深圳客服二面:口诉八股大战:大概囊括网络,浏览器渲染原理,动画优化,时间循环,任务队列等等(你能想到的简单八股通通拉出来鞭尸😋)算法题:笔试题6道:1:找出数组内重复的数,arr[0]-arr[n]内的数大小为[1-n],例如[1,2,2,3,3]返回[2,3],要求o(n),且不使用任何额外空间(做到了o(n),空间方面欠佳,给面试官说进入下一题,做不来了)2:原滋原味的继承(所以继承真滴很重要)3:力扣股票购买时机难度中等其他滴也忘记了,因为拿到offer后鼠鼠一下子就落地了,脑子自动过滤掉可能会攻击鼠鼠的记忆😷~~~秒过深圳客服三面:项目大战参与战斗的人员有:成员1:表单封装及其底层原理,使用成本的优化,声明式表单成员2:公司内部库生命周期管理成员3:第三方库和内部库冲突如何源码断点调试并打补丁解决成员4:埋点的艺术成员5:线上项目捷报频传如何查出内鬼成员6:大文件分片的风流趣事成员7:设计模式对对碰成员8:我构建hooks应对经理的新增的小需求的故事可能项目回答的比较流利,笔试题3道,都很简单,相信大家应该都可以手拿把掐😇~~~过过过无hr面后续煎熬等待几天直接hr打电话发offer了,希望大家也可以拿到自己心仪的offer
法力无边年:牛哇,你真是准备得充分,我对你没有嫉妒,都是实打实付出
查看21道真题和解析
点赞 评论 收藏
分享
评论
3
21
分享

创作者周榜

更多
牛客网
牛客企业服务