js实现切面
在JavaScript中实现切面编程(AOP,面向切面编程)通常通过高阶函数、装饰器或Proxy对象实现,以下是几种常见方法:
使用高阶函数包装
通过高阶函数在原函数前后注入逻辑,实现简单的切面效果:
function withLogging(fn) {
return function(...args) {
console.log(`Entering ${fn.name}`);
const result = fn.apply(this, args);
console.log(`Exiting ${fn.name}`);
return result;
};
}
// 原始函数
function calculate(a, b) {
return a + b;
}
// 应用切面
const wrappedCalc = withLogging(calculate);
wrappedCalc(2, 3); // 输出日志并计算结果
使用ES7装饰器(需Babel转译)
装饰器语法更直观地实现切面:
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
return original.apply(this, args);
};
return descriptor;
}
class Calculator {
@log
add(a, b) {
return a + b;
}
}
new Calculator().add(1, 2); // 自动输出调用日志
使用Proxy对象
Proxy可以拦截目标对象的各种操作:
const handler = {
get(target, prop) {
if (typeof target[prop] === 'function') {
return (...args) => {
console.log(`Calling ${prop} with`, args);
return target[prop](...args);
};
}
return target[prop];
}
};
const obj = {
add(a, b) { return a + b; }
};
const proxied = new Proxy(obj, handler);
proxied.add(1, 2); // 自动输出调用日志
使用AOP库
现有库如aspect.js提供更完整的AOP支持:

import { before, after } from 'aspect.js';
class AuthService {
@before(function(args) {
console.log('Before login with', args);
})
login(user) {
// 登录逻辑
}
}
注意事项
- 装饰器语法需要Babel插件
@babel/plugin-proposal-decorators支持 - Proxy无法拦截箭头函数
- 生产环境建议使用成熟的AOP库以获得更好的类型支持和错误处理
选择哪种方式取决于项目需求和技术栈,装饰器方案在TypeScript项目中集成度较高,而Proxy方案更适合动态拦截场景。






