闭包是依赖注入的轻量级载体,不自动解析依赖,而是通过函数作用域隔离、参数传递与返回接口显式传递依赖,支持IIFE单例和工厂多实例两种模式,确保依赖来源清晰、测试友好、无全局污染。

闭包本身不直接“实现”模块间依赖注入,而是提供一种天然的、轻量级的封装机制,让依赖注入变得简单、可控、无副作用。它不依赖框架或容器,靠函数作用域隔离 + 参数传递 + 返回接口完成依赖的显式传递与使用。
闭包是依赖注入的“载体”,不是注入器
闭包的核心价值在于捕获并持有外部传入的依赖,使其在返回的模块实例中持续可用,且不污染全局作用域。它不自动扫描或解析依赖,而是把“谁提供依赖”和“谁消费依赖”的关系,交由调用方明确决定——这正是手动依赖注入(Manual DI)的典型做法。
- 依赖必须由上层(如启动文件、配置中心、服务工厂)显式传入,闭包只是把它“记住”
- 模块内部无法自行 new 或 require 依赖,所有外部资源都来自参数
- 返回的模块接口只能访问闭包内已捕获的依赖,天然防止越权调用
两种主流闭包注入模式
根据使用场景,闭包支持单例式和工厂式两种注入结构:
- IIFE 单例注入:适合全局唯一、状态轻量的 SDK(如日志、埋点)。依赖在 IIFE 执行时一次性注入,后续所有调用共享同一组依赖实例
- 工厂函数多实例注入:适合需隔离上下文的场景(如多租户推送、不同环境 API 客户端)。每次调用工厂函数都生成独立闭包,依赖随配置重新绑定,互不影响
依赖注入的具体写法
关键在于模块导出的是函数而非对象,接收依赖作为参数,并返回具备业务能力的模块实例:
- 模块定义(module.js)导出一个函数,形参接收 config、db、logger 等依赖项
- 服务入口(server.js)负责组装依赖,调用该函数获得模块实例
- 模块内部可组合多个依赖,例如用 logger 包裹 db 操作,用 config 校验参数,全部在闭包内闭环
为什么比全局变量或硬编码更安全?
闭包注入本质是“一次传入、长期持有、局部可见”,规避了常见陷阱:
- 避免全局变量导致的并发冲突或状态污染(尤其在 Node.js 多请求场景)
- 杜绝配置文件被写死(如 config_beta.js),同一套模块代码可适配多套环境
- 单元测试时可轻松传入 mock 依赖,无需 patch 全局或修改源码
- 依赖来源清晰可追溯,IDE 能识别参数类型,重构时不会误删关键引用

















