以下是一个基于 JavaScript 的简单依赖注入(DI)容器实现,包含核心功能解析和代码示例:
一、核心实现原理class Container { constructor() { this.dependencies = {}; // 存储依赖项 } // 注册依赖项 register(name, dependency, singleton = false) { this.dependencies[name] = { factory: typeof dependency === 'function' ? dependency : () => dependency, // 支持值/函数/类 singleton, instance: null }; } // 解析依赖项 resolve(name) { const dep = this.dependencies[name]; if (!dep) throw new Error(`Dependency not found: ${name}`); // 单例模式直接返回实例 if (dep.singleton && dep.instance) { return dep.instance; } // 调用工厂函数并传入容器实例(支持嵌套依赖) const instance = dep.factory(this); // 单例模式缓存实例 if (dep.singleton) { dep.instance = instance; } return instance; } // 清除依赖(测试用) clear(name) { if (name) delete this.dependencies[name]; else this.dependencies = {}; }}二、关键特性说明依赖注册
支持三种形式:值、工厂函数、类
通过 singleton 参数控制单例模式
依赖解析
自动处理嵌套依赖(通过传递容器实例)
单例模式首次创建后缓存实例
扩展性
可通过修改工厂函数支持更复杂的构造逻辑
容器实例可作为参数传递实现依赖链
三、完整使用示例// 1. 定义基础服务function Logger() { return { log: msg => console.log(`[LOG] ${msg}`) };}// 2. 定义依赖Logger的服务function DataService(container) { const logger = container.resolve('logger'); return { getData: () => { logger.log('Fetching data...'); return ['item1', 'item2']; } };}// 3. 定义嵌套依赖服务function UserService(container) { const dataService = container.resolve('dataService'); return { getUserData: () => dataService.getData() };}// 4. 使用容器const container = new Container();container.register('logger', Logger, true); // 单例Loggercontainer.register('dataService', DataService); // 非单例DataServicecontainer.register('userService', UserService); // 非单例UserService// 5. 解析服务const userService = container.resolve('userService');console.log(userService.getUserData());// 输出:// [LOG] Fetching data...// ['item1', 'item2']四、进阶用法示例// 1. 使用Class定义服务class ApiClient { constructor(logger) { this.logger = logger; } fetch() { this.logger.log('API request sent'); return { success: true }; }}// 2. 注册Class服务(通过工厂函数)container.register('apiClient', (container) => { const logger = container.resolve('logger'); return new ApiClient(logger);}, true);// 3. 使用服务const apiClient = container.resolve('apiClient');console.log(apiClient.fetch());// 输出:// [LOG] API request sent// { success: true }五、设计优势分析- 解耦性:服务间通过容器交互而非直接引用
- 可测试性:可轻松替换mock依赖
- 灵活性:支持多种服务定义方式
- 生命周期控制:通过singleton参数管理实例创建
六、典型应用场景- 大型前端应用的模块管理
- 后端服务的中间件组织
- 需要频繁替换实现的测试环境
- 复杂组件间的依赖协调
这个实现虽然简洁,但包含了DI容器的核心功能。实际项目中可根据需要扩展以下功能:
- 依赖项参数化配置
- 生命周期钩子
- 异步依赖支持
- 依赖项元数据管理