闭包可实现aop式before/after拦截,无需装饰器:通过封装原函数与前后回调,共享作用域并支持参数、this、返回值操作;支持同步、异步及错误处理,且可链式叠加增强。

闭包可以轻松封装函数执行前后的逻辑,实现类似 AOP 的 Before/After 拦截,无需框架或装饰器语法(在不支持装饰器的环境如老版 JS 中尤其有用)。
核心思路:用闭包保存原函数和拦截逻辑
把原始函数、before 回调、after 回调一起“封进”一个新函数里,新函数每次调用时自动触发 before → 执行原函数 → after。
- 闭包让 before/after 和原函数共享作用域,可访问相同参数、上下文(this)、甚至修改返回值或抛出异常
- 返回的新函数就是被拦截后的“增强版”函数,可复用、可链式增强
基础 Before/After 拦截实现
下面是一个通用的拦截器工厂函数:
function intercept(fn, before = () => {}, after = () => {}) {
return function(...args) {
const ctx = this;
before.apply(ctx, args);
const result = fn.apply(ctx, args);
after.apply(ctx, [result, ...args]);
return result;
};
}
使用示例:
const original = (x, y) => x + y;
const loggedAdd = intercept(
original,
(x, y) => console.log(`[Before] Adding ${x} and ${y}`),
(result, x, y) => console.log(`[After] Result: ${result}`)
);
loggedAdd(3, 5);
// 输出:
// [Before] Adding 3 and 5
// [After] Result: 8
支持异步函数与错误处理的增强版
真实场景中常需处理 Promise 或 try/catch。闭包依然适用,只需在内部判断返回值类型:
function interceptAsync(fn, before = () => {}, after = () => {}, onError = () => {}) {
return async function(...args) {
const ctx = this;
try {
before.apply(ctx, args);
const result = await fn.apply(ctx, args);
after.apply(ctx, [result, ...args]);
return result;
} catch (err) {
onError.apply(ctx, [err, ...args]);
throw err;
}
};
}
- before 和 onError 同步执行;after 在 Promise resolve 后执行
- 闭包确保所有回调都能访问到 this 和 args,且生命周期独立于调用时机
叠加多个拦截(链式增强)
闭包天然支持组合:每次拦截都返回一个新函数,可逐层包裹:
const withLog = intercept(fn, () => console.log('log start'), () => console.log('log end'));
const withTimer = intercept(withLog, () => console.time('exec'), () => console.timeEnd('exec'));
// withTimer 现在同时具备日志和计时能力
注意顺序:外层拦截的 before 最先执行,外层 after 最后执行(类似洋葱模型)。











