介绍
js装饰器目前(2023/3/24)还处于提案Stage-3阶段,一共有 5 个状态,分别是: Stage 0: Strawman(展示阶段) Stage 1: Proposal(征求意见阶段) Stage 2: Draft(草案阶段) Stage 3: Candidate(候选阶段) Stage 4: Finished(定案阶段)。现在使用装饰器的语法,需要借助babel来编译。 学过java的,看到js的@xxx装饰器语法,很容易想到java的注解。虽然实现的功能有些类似,但内部的实现机制不同。效果上都是在不改变原有类、属性、方法的情况下,给它们增加额外的功能,并且同一个装饰器可以增强多个类、属性、方法,达到代码的最大复用。
环境配置
vscode里编辑@xxx默认会报错
需要在设置里开启装饰器的支持
编译报错,安装装饰器支持插件:
yarn add @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators
plugin-proposal-decorators支持装饰器语法的插件,plugin-proposal-class-properties编译class的插件 package.json文件中配置:
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
]
]
}
使用案例:
下面可以开始使用装饰器语法写代码了。
类装饰器
const test = (target) => {
target.sName = 'Tom'
target.getAge = function () {
return 20;
}
}
@test
class Student{
}
console.dir(Student);
通过浏览器调试工具的Sources里可以看到语法糖编译后的代码:
var _class;
let Student = test(_class = class Student {}) || _class;
console.dir(Student);
将Student类做为参数传入test函数中,target就是Student类,在类上挂载属性和方法 如果装饰器test有返回值,则使用返回值替代Student类,没有返回值则为Student类。
方法装饰器
function log(target, name, descriptor) {
// 保存原始方法
const original = descriptor.value;
// 修改方法的行为
descriptor.value = function (...args) {
console.log(`Before calling ${name} with arguments: ${args}`);
const result = original.apply(this, args);
console.log(`After calling ${name}: ${result}`);
return result;
};
// 返回修改后的方法
return descriptor;
}
// 使用装饰器修改方法的行为
class Student {
@log
myMethod(arg1, arg2) {
return arg1 + arg2;
}
}
// 创建 Student 的实例
const myObject = new Student();
// 调用 Student 的方法
myObject.myMethod(1, 2);
方法装饰器可以在不改变原有方法的情况下,在方法执行前后插入业务代码,如打印日志、数据校验等。运用了代理模式,可以达到AOP切面编程效果。
属性装饰器
function readonly(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
class Person {
@readonly
name = '张三';
}
const p = new Person();
p.name = '李四'; // 抛出 TypeError
属性装饰器可以修改属性是否只读,是否可以迭代,是否可删除。
js的装饰器和java注解的区别
JavaScript装饰器是一种函数,它可以修改类、方法或属性的行为。Java注解是一种元数据,它可以用于提供类、方法或属性的信息。 JavaScript 装饰器是在运行时执行的,它们可以动态地修改类、方法或属性的行为。Java注解是通过反射机制实现的,它们可以在运行时被读取和处理,但不会动态改变原有的类、方法或属性。