全部学科
Python全栈
python
NodeJS全栈
nodejs
📝 1 篇文章 20 道配套习题

JS设计模式与架构思想

专题说明

本专题系统讲解JavaScript设计模式与架构思想,涵盖创建型、结构型、行为型模式在前端的应用,以及MVC/MVVM架构、单向数据流等现代前端架构思想,帮助开发者构建可维护、可扩展的前端应用。

学习目标

  1. 理解依赖注入与控制反转原理,掌握DI容器实现
  2. 掌握观察者模式、代理模式、装饰器模式等经典设计模式
  3. 理解异步流程控制模式,合理选择串行、并行、竞速策略
  4. 理解MVC/MVVM架构分层思想,明确各层职责边界
  5. 掌握单向数据流与状态管理最佳实践

学习内容

  • 依赖注入与控制反转(IoC)
  • 观察者模式与事件驱动
  • 代理模式与装饰器模式
  • 异步设计模式
  • MVC/MVVM架构思想
  • 单向数据流与状态管理

学习建议

  1. 先理解设计模式的意图和适用场景,再学习具体实现
  2. 结合实际项目对比不同架构方案的优缺点
  3. 关注设计模式在前端框架中的实际应用
  4. 注重架构分层思想,明确各层职责边界

📝 配套习题(20 题)

💡 参考答案在文末
判断题
1

在MVVM架构中,ViewModel应该包含业务逻辑和数据处理代码,包括API调用、数据转换、复杂计算等操作。

A

B

2

依赖倒置原则(DIP)要求高层模块依赖低层模块,低层模块实现高层模块定义的接口,这样可以保证高层模块的稳定性。

A

B

单选题
3

以下代码实现了装饰器模式,请分析其核心设计特点:

JavaScript
// 基础组件
class Coffee {
  cost() { return 10; }
}

// 装饰器基类
class CoffeeDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }
  cost() { return this.coffee.cost(); }
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
  cost() { return this.coffee.cost() + 2; }
}

class SugarDecorator extends CoffeeDecorator {
  cost() { return this.coffee.cost() + 1; }
}

// 使用
let coffee = new Coffee();
coffee = new MilkDecorator(coffee);  // 加牛奶
coffee = new SugarDecorator(coffee); // 加糖
console.log(coffee.cost()); // 13

这段代码体现的装饰器模式核心特点是什么?

A

通过继承扩展功能,子类增强父类方法

B

通过组合包装对象,动态添加功能而不修改原对象

C

通过代理控制访问,验证权限后才执行方法

D

通过工厂创建对象,封装复杂的创建逻辑

4

以下关于模块化设计原则的描述中,哪一项是正确的?

A

高内聚低耦合原则要求模块内部功能分散,模块间依赖紧密

B

模块应暴露最小接口,隐藏内部实现细节,这是封装原则的体现

C

循环依赖是模块化设计中允许的结构,不影响代码可维护性

D

模块粒度越大越好,减少模块数量可以降低管理成本

5

以下代码展示的是哪种依赖注入方式?

JavaScript
class UserService {
  constructor(userRepository, logger) {
    this.userRepository = userRepository;
    this.logger = logger;
  }
}

// 使用
const userService = container.resolve(UserService);
A

属性注入

B

构造函数注入

C

接口注入

D

方法注入

6

以下代码实现了简单的事件驱动系统,请分析其设计模式特征:

JavaScript
class EventEmitter {
  constructor() {
    this.events = new Map();
  }

  on(event, listener) {
    if (!this.events.has(event)) {
      this.events.set(event, new Set());
    }
    this.events.get(event).add(listener);
  }

  emit(event, ...args) {
    if (this.events.has(event)) {
      this.events.get(event).forEach(listener => listener(...args));
    }
  }

  off(event, listener) {
    if (this.events.has(event)) {
      this.events.get(event).delete(listener);
    }
  }
}

这段代码体现的是哪种设计模式的实现?

A

观察者模式

B

发布-订阅模式

C

策略模式

D

命令模式

多选题
7

GoF设计模式按目的分为三大类,以下关于设计模式分类和SOLID原则的描述哪些是正确的?

A

创建型模式关注对象创建过程,包括工厂、抽象工厂、单例、建造者、原型模式

B

结构型模式关注类和对象的组合,包括适配器、装饰器、代理、外观、组合、桥接模式

C

行为型模式关注对象间的通信和职责分配,包括观察者、策略、命令、迭代器、模板方法模式

D

单一职责原则(SRP)要求一个类只有一个变化原因,一个类只负责一项职责

E

开闭原则(OCP)要求对扩展开放、对修改关闭,通过抽象和多态实现

F

所有23种GoF设计模式都适用于JavaScript,实现方式与Java完全一致

8

Promise是JavaScript异步编程的核心,以下关于Promise内部实现机制的描述哪些是正确的?

A

Promise内部使用微任务队列(Microtask Queue)执行then回调,优先于宏任务

B

Promise状态只能从pending变为fulfilled或rejected,不可逆转

C

then方法返回新的Promise,实现链式调用,原Promise状态不影响新Promise

D

Promise内部维护回调队列,pending状态时存储回调,resolve时批量执行

E

catch方法实际上是then(null, onRejected)的语法糖

F

Promise.all返回的Promise在任一输入Promise reject时立即reject

9

代理模式在JavaScript中有广泛应用,以下哪些是代理模式的典型应用场景?

A

虚拟代理:延迟加载大图片,先显示占位图,图片加载完成后再替换

B

保护代理:控制对象访问权限,验证用户身份后才能访问敏感方法

C

缓存代理:为昂贵操作(如API请求、计算)提供结果缓存,避免重复执行

D

智能引用代理:在对象被访问时自动执行额外操作,如引用计数、日志记录

E

ES6 Proxy可拦截对象的所有操作,包括属性读取、设置、删除、函数调用

F

装饰器模式与代理模式本质相同,都是为对象添加额外功能

10

关于工厂模式的变体及其在JavaScript中的应用,以下哪些描述是正确的?

A

简单工厂模式通过一个工厂类创建所有产品,违反开闭原则但实现简单

B

工厂方法模式将工厂抽象化,每个产品对应一个工厂类,符合开闭原则

C

抽象工厂模式创建相关对象家族,每个具体工厂可创建多个产品等级

D

JavaScript中常用对象字面量或类语法实现工厂,无需复杂继承结构

E

工厂模式的主要目的是优化对象创建性能,减少内存占用

F

注册表模式(Registry)可配合工厂模式,实现按名称创建产品的灵活扩展

11

关于JavaScript中依赖注入(DI)容器的实现,以下哪些描述是正确的?

A

DI容器通过反射机制自动解析依赖关系,无需开发者手动指定依赖

B

容器使用Map结构存储服务注册信息,键为服务标识符,值为工厂函数或实例

C

依赖注入可以解决循环依赖问题,容器会自动检测并报错

D

生命周期管理包括Transient(每次创建新实例)和Singleton(全局单例)两种模式

E

容器在解析依赖时采用延迟加载策略,只有首次使用时才创建实例

F

依赖注入本质上是控制反转(IoC)思想的一种具体实现方式

12

关于JavaScript中观察者模式的实现与内存管理,以下哪些描述是正确的?

A

观察者模式中,Subject(主题)维护一个观察者列表,当状态变化时通知所有观察者

B

观察者必须实现update方法,这是观察者模式的标准接口定义

C

内存泄漏风险主要来自未取消订阅的观察者引用,应在组件销毁时调用unsubscribe

D

使用WeakMap存储观察者可以自动解决内存泄漏问题

E

发布-订阅模式是观察者模式的变体,引入消息调度中心实现完全解耦

F

观察者模式的同步通知机制在观察者数量多时会影响性能

13

JavaScript异步编程有多种模式,以下关于各异步模式的对比分析哪些是正确的?

A

Callback模式最原始,存在回调地狱问题,但性能最优无额外开销

B

Promise链式调用解决了回调地狱,通过then/catch实现错误集中处理

C

async/await语法糖让异步代码像同步代码一样书写,本质上仍是Promise

D

Generator配合co库可实现类似async/await的效果,但需手动调用next()

E

事件驱动模式适合I/O密集场景,通过EventEmitter实现非阻塞事件处理

F

Reactive模式(RxJS)将异步数据流视为可观察序列,支持丰富的操作符组合

14

控制反转(IoC)是软件设计的核心原则,以下哪些是实现IoC的正确方式?

A

依赖注入(DI):通过构造函数、属性或接口注入依赖对象

B

依赖查找(DL):对象主动从服务定位器中获取所需依赖

C

模板方法模式:父类定义算法骨架,子类实现具体步骤

D

策略模式:在运行时动态选择算法实现,由客户端决定使用哪个策略

E

工厂模式:将对象创建逻辑委托给工厂类,调用者无需知道具体创建过程

F

观察者模式:主题状态变化时主动通知观察者,观察者被动响应

15

前端架构模式从MVC演进而来,以下关于MVC、MVP、MVVM架构模式的对比描述哪些是正确的?

A

MVC中Model负责数据管理,View负责界面展示,Controller处理用户输入协调Model和View

B

MVC中View直接观察Model变化更新界面,可能导致View与Model耦合

C

MVP将Controller改为Presenter,View不直接访问Model,通过Presenter间接通信

D

MVVM引入ViewModel作为View的抽象映射,通过数据绑定自动同步View和Model

E

MVVM的双向数据绑定减少了手动DOM操作,但可能隐藏数据流,调试困难

F

React采用的是MVVM架构,通过虚拟DOM实现高效的数据绑定

16

JavaScript模块化规范经历了多个阶段演进,以下关于各异步模块规范的描述哪些是正确的?

A

CommonJS使用同步require加载模块,适合Node.js服务端环境

B

AMD(Asynchronous Module Definition)使用异步加载,require.js是其典型实现

C

ES Modules(ESM)是官方标准,使用静态import/export语法,支持静态分析

D

UMD(Universal Module Definition)兼容CommonJS、AMD和全局变量,适合跨环境库

E

ES Modules的import语句必须在模块顶层使用,不支持条件导入

F

CommonJS模块导出的是值的拷贝,ES Modules导出的是值的实时引用

填空题
17

控制反转(IoC)的核心思想是将对象的____________责任从对象本身转移到外部容器。在依赖注入中,常用三种注入方式:通过____________注入必需依赖、通过____________注入可选依赖、通过接口注入实现解耦。

18

异步流程控制有多种模式。串行执行使用____________或reduce逐个执行异步任务。并行执行使用____________同时启动所有任务,等待全部完成。竞速模式使用____________返回最先完成的任务结果。批量控制使用Promise.allSettled获取所有任务的完成状态(无论成功或失败)。

19

MVVM框架实现双向数据绑定主要有两种方案。Vue2使用____________配合发布订阅模式,劫持对象属性的getter/setter,在数据变化时触发________________________。Vue3改用Proxy代理整个对象,可监听数组变化和新增属性,性能更优。

20

JavaScript中实现单例模式有多种方式。使用ES6 class实现时,可通过____________存储唯一实例,在构造函数中判断若实例已存在则____________。使用模块模式时,利用ES模块的____________(模块只执行一次),直接导出实例即可。惰性初始化单例使用立即执行函数(IIFE)或Symbol保障实例私有性。

参考答案
1.错误 2.错误 3.B 4.B 5.B 6.B 7.A;B;C;D;E 8.A;B;C;D;E;F 9.A;B;C;D;E 10.A;B;C;D;F 11.B;D;E;F 12.A;C;E;F 13.A;B;C;D;E;F 14.A;B;C;E 15.A;B;C;D;E 16.A;B;C;D;E;F 17.创建和依赖管理;构造函数;属性/Setter方法 18.async/await配合循环;Promise.all;Promise.race 19.数据劫持(Object.defineProperty);依赖收集;派发更新 20.静态私有属性;返回已有实例;单例特性
想在手机上练习这套专题?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一个专题 JS浏览器与DOM高级
下一个专题 → JS高级性能分析
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码