js 实现aop
在JavaScript中实现AOP(面向切面编程)
AOP的核心思想是将横切关注点(如日志、性能监控、事务管理等)与业务逻辑分离。JavaScript可以通过以下几种方式实现AOP:
使用高阶函数包装
通过高阶函数对目标函数进行包装,在目标函数执行前后插入额外逻辑。

function wrap(targetFunc, beforeFunc, afterFunc) {
return function() {
beforeFunc && beforeFunc.apply(this, arguments);
const result = targetFunc.apply(this, arguments);
afterFunc && afterFunc.apply(this, arguments);
return result;
};
}
// 示例用法
const originalFunc = () => console.log('业务逻辑');
const loggedFunc = wrap(
originalFunc,
() => console.log('调用前日志'),
() => console.log('调用后日志')
);
loggedFunc();
修改Function原型
通过扩展Function原型实现AOP功能,这种方式会影响所有函数。

Function.prototype.before = function(beforeFunc) {
const original = this;
return function() {
beforeFunc.apply(this, arguments);
return original.apply(this, arguments);
};
};
Function.prototype.after = function(afterFunc) {
const original = this;
return function() {
const result = original.apply(this, arguments);
afterFunc.apply(this, arguments);
return result;
};
};
// 示例用法
const func = () => console.log('业务逻辑');
const wrappedFunc = func
.before(() => console.log('前置通知'))
.after(() => console.log('后置通知'));
wrappedFunc();
使用ES6 Proxy
利用Proxy对象可以拦截目标对象的操作,实现更灵活的AOP。
function createAopProxy(target, advice) {
return new Proxy(target, {
apply(target, thisArg, args) {
advice.before && advice.before.apply(thisArg, args);
const result = Reflect.apply(target, thisArg, args);
advice.after && advice.after.apply(thisArg, args);
return result;
}
});
}
// 示例用法
const targetFunc = () => console.log('业务逻辑');
const advisedFunc = createAopProxy(targetFunc, {
before: () => console.log('前置增强'),
after: () => console.log('后置增强')
});
advisedFunc();
使用装饰器(ES7/TypeScript)
在支持装饰器的环境中,可以使用装饰器语法实现AOP。
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`调用 ${name} 方法`);
return original.apply(this, args);
};
return descriptor;
}
class Example {
@log
method() {
console.log('业务逻辑');
}
}
new Example().method();
注意事项
- 原型扩展会影响所有函数,可能引起意想不到的副作用
- Proxy方式需要现代浏览器或Node.js环境支持
- 装饰器目前仍是ECMAScript提案,需要Babel等工具转译
- 性能敏感场景需谨慎使用AOP,过多的拦截可能影响性能
每种实现方式各有优缺点,应根据具体项目需求和运行环境选择合适的方法。






