当前位置: 首页 > 科技观察

面试官:谈谈你对TypeScript装饰器的理解?应用场景?

时间:2023-03-19 01:17:35 科技观察

1.什么是装饰器?它是一种特殊类型的声明,可以附加到类声明、方法、访问器、属性或参数上。它是一种在不改变原始类和使用继承的情况下动态扩展对象的方法。功能是一样的,本质上也不是什么高大上的结构,只是一个普通的功能。@expression的形式其实就是Object.defineProperty的语法糖。Expression求值后也必须是一个函数,在运行时会被调用和修饰声明信息作为参数传递2.如何使用由于typescript是一个实验特性,如果要使用,需要在启动tsconfig.json文件,如下:{"compilerOptions":{"target":"ES5","experimentalDecorators":true}}typescript装饰器的使用和javascript基本相同。类装饰器可以装饰:类方法/属性参数访问器类装饰比如声明一个函数addAge,为Class的属性age添加age.functionaddAge(constructor:Function){constructor.prototype.age=18;}@addAgeclassPerson{name:string;age!:number;constructor(){this.name='huihui';}}letperson=newPerson();console.log(person.age);//18上面的代码其实等价于下面的形式:Person=addAge(functionPerson(){...});从上面可以看出,装饰器作为修饰类时,会传入构造函数。constructor.prototype.age是在每个实例化的对象上添加一个age属性方法/属性装饰。同样,装饰器可以用来修饰类方法。这时装饰器函数接收到的参数变成:target:对象的原型propertyKey:方法的名称descriptor:方法的属性描述符。可以看到,这三个属性其实就是Object.defineProperty的三个参数。如果是类的属性,则不传递第三个参数。示例://声音明装饰器修改方法/属性函数method(target:any,propertyKey:string,descriptor:PropertyDescriptor){console.log(target);console.log("prop"+propertyKey);console.log("desc"+JSON.stringify(描述符)+"\n\n");descriptor.writable=false;};functionproperty(target:any,propertyKey:string){console.log("target",target)console.log("propertyKey",propertyKey)}classPerson{@propertyname:string;constructor(){this.name='huihui';}@methodsay(){return'instancemethod';}@methodstaticrun(){return'staticmethod';}}constxmz=newPerson();//修改实例方法sayxmz.say=function(){return'edit'}的输出如下图:参数decoration接收3个参数,分别是:target:当前对象的原型propertyKey:参数名称index:参数在数组中的位置{问候(@logParametermessage:string):string{return`hello${message}`;}}constemp=newEmployee();emp.greet('你好');如下图输入:accessor修饰的使用方式与方法修饰相同为,如下:descriptor)+"\n\n");};classPerson{_name:string;constructor(){this._name='huihui';}@modificationgetname(){returnthis._name}}如果装饰器工厂要传递参数,要把装饰器变成工厂函数,只需要在装饰器函数内部再添加一个函数,如下:functionaddAge(age:number){returnfunction(constructor:Function){constructor.prototype.age=age}}@addAge(10)classPerson{name:string;age!:number;constructor(){this.name='huihui';}}letperson=newPerson();执行顺序当一个语句应用多个装饰器时,会从上到下依次对装饰器表达式求值,求值结果会被视为一个函数,从下到上依次调用,例如如下:functionf(){console.log("f():evaluated");returnfunction(target,propertyKey:string,descriptor:PropertyDescriptor){console.log("f():called");}}functiong(){console.log("g():evaluated");returnfunction(target,propertyKey:string,descriptor:PropertyDescriptor){console.log("g():called");}}classC{@f()@g()method(){}}//输出f():evaluatedg():evaluatedg():calledf():called三、应用场景可见,使用装饰器有两个显着的好处:代码的可读性变强,装饰器的名字相当于注释。在不改动原有代码的情况下,对原有功能进行扩展。可读性之后,对于已有的类,可以在不改变原有代码的情况下,利用装饰器的特性,扩展原有的功能。参考https://www.tslang.cn/docs/handbook/decorators。htmlhttps://juejin.cn/post/6844903876605280269#heading-5