闭包是函数式编程中封装执行契约的核心机制,支持自定义执行时机、重试、缓存、权限校验等策略,且不侵入业务逻辑;通过高阶函数动态注入、组合多层契约,并维持私有状态。

闭包是构建函数式编程工具箱的核心机制,它让函数能携带环境、延迟执行、封装契约逻辑。所谓“自定义执行契约”,指的是为函数调用约定行为边界——比如执行时机、重试策略、缓存规则、错误兜底、权限校验等——而这些契约不侵入业务逻辑本身,而是通过闭包动态注入。
用闭包封装可配置的执行策略
把契约抽象成高阶函数,接收业务函数和策略参数,返回一个带契约的新函数。闭包捕获策略配置,避免每次调用重复传参。
- 例如:带重试次数与延迟的异步调用封装
-
retryable = (fn, maxRetries = 2, delayMs = 1000) => {
return async function(...args) {
for (let i = 0; i try { return await fn(...args); }
catch (e) { if (i === maxRetries) throw e; await new Promise(r => setTimeout(r, delayMs)); }
}
};
};
const safeFetch = retryable(fetchUser, 3, 500); // 闭包已固化策略
用闭包实现惰性+条件化执行契约
契约可决定“是否执行”或“何时执行”。闭包保存判断逻辑与原始函数,直到真正被调用且条件满足才触发。
- 例如:仅在用户登录后才执行的函数
-
requireAuth = (fn, authCheck = () => !!session.user) => {
return function(...args) {
if (!authCheck()) throw new Error('Unauthorized');
return fn(...args);
};
};
const protectedAction = requireAuth(deletePost, () => hasRole('admin')); - 关键点:authCheck 和 fn 都被闭包捕获;每次调用 protectedAction 都重新检查,但策略逻辑只定义一次
用闭包组合多层契约(Pipeline 式)
多个契约函数可像管道一样组合,每个闭包只关注单一职责,最终返回一个融合全部契约的函数。
- 例如:日志 + 缓存 + 超时三重契约
-
composeContract = (...fns) => (fn) => fns.reduceRight((acc, contract) => contract(acc), fn);
const loggedCachedTimed = composeContract(
withTimeout(3000),
withCache({ ttl: 60000 }),
withLogging('api-call')
)(fetchData); - 每个 withXxx 都是返回闭包的高阶函数,它们按需捕获各自参数,并在最终调用链中依次生效
用闭包维持契约状态(有状态契约)
某些契约需要内部状态,如限流器的计数、熔断器的状态机。闭包天然支持私有状态隔离,不同实例互不影响。
- 例如:基于时间窗口的请求计数器
-
rateLimit = (maxPerWindow = 10, windowMs = 60000) => {
const calls = [];
return (fn) => async function(...args) {
const now = Date.now();
calls.push(now);
// 清理过期记录
for (let i = 0; i if (calls[i] else break;
}
if (calls.length > maxPerWindow) throw new Error('Rate limit exceeded');
return await fn(...args);
};
};
const limitedApi = rateLimit(5, 10000)(callExternalService);











