js实现aop
在 JavaScript 中实现 AOP(面向切面编程)
AOP 是一种编程范式,允许在不修改原有代码的情况下,通过“切面”动态插入横切关注点(如日志、性能监控等)。以下是几种常见的实现方式:
通过高阶函数实现
利用 JavaScript 的函数特性,通过高阶函数包装目标函数:
function wrap(targetFunc, beforeFunc, afterFunc) {
return function() {
beforeFunc.apply(this, arguments);
const result = targetFunc.apply(this, arguments);
afterFunc.apply(this, arguments);
return result;
};
}
// 示例
const originalFunc = () => console.log("核心逻辑");
const loggedFunc = wrap(
originalFunc,
() => console.log("调用前日志"),
() => console.log("调用后日志")
);
loggedFunc();
使用原型链扩展
通过修改 Function.prototype 实现链式调用:
Function.prototype.before = function(fn) {
const self = this;
return function() {
fn.apply(this, arguments);
return self.apply(this, arguments);
};
};
Function.prototype.after = function(fn) {
const self = this;
return function() {
const result = self.apply(this, arguments);
fn.apply(this, arguments);
return result;
};
};
// 示例
const func = () => console.log("核心逻辑");
func.before(() => console.log("前置逻辑"))()
.after(() => console.log("后置逻辑"));
基于 ES6 Proxy 实现
利用 Proxy 对象拦截目标对象的操作:
const createAopProxy = (target, advice) => {
return new Proxy(target, {
get(target, propKey) {
const origMethod = target[propKey];
if (typeof origMethod === 'function') {
return function(...args) {
advice.before && advice.before(...args);
const result = origMethod.apply(this, args);
advice.after && advice.after(result);
return result;
};
}
return origMethod;
}
});
};
// 示例
const obj = { greet: name => `Hello, ${name}` };
const proxied = createAopProxy(obj, {
before: name => console.log(`调用参数: ${name}`),
after: res => console.log(`返回结果: ${res}`)
});
proxied.greet("World");
使用装饰器(ES7+)
在支持装饰器的环境中(如 Babel 或 TypeScript),可直接使用语法糖:

function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`调用 ${name} 参数:`, args);
const result = original.apply(this, args);
console.log(`调用 ${name} 结果:`, result);
return result;
};
return descriptor;
}
class Example {
@log
greet(name) { return `Hello, ${name}`; }
}
new Example().greet("AOP");
注意事项
- 性能影响:代理或装饰器可能引入额外开销,高频调用场景需谨慎。
- this 绑定:确保切面函数中的
this上下文正确。 - 错误处理:可在切面中加入
try/catch实现统一错误处理。
以上方法可根据具体需求选择,高阶函数和原型链适合简单场景,Proxy 和装饰器更适合复杂系统。






