装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上

成都创新互联专注为客户提供全方位的互联网综合服务,包含不限于成都网站设计、成都网站制作、乡宁网络推广、小程序设计、乡宁网络营销、乡宁企业策划、乡宁品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联为所有大学生创业者提供乡宁建站搭建服务,24小时服务热线:028-86922220,官方网址:www.cdcxhl.com
是一种在不改变原类和使用继承的情况下,动态地扩展对象功能
同样的,本质也不是什么高大上的结构,就是一个普通的函数,@expression 的形式其实是Object.defineProperty的语法糖
expression求值后必须也是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入
由于typescript是一个实验性特性,若要使用,需要在tsconfig.json文件启动,如下:
- {
 - "compilerOptions": {
 - "target": "ES5",
 - "experimentalDecorators": true
 - }
 - }
 
typescript装饰器的使用和javascript基本一致
类的装饰器可以装饰:
例如声明一个函数 addAge 去给 Class 的属性 age 添加年龄.
- function addAge(constructor: Function) {
 - constructor.prototype.age = 18;
 - }
 - @addAge
 - class Person{
 - name: string;
 - age!: number;
 - constructor() {
 - this.name = 'huihui';
 - }
 - }
 - let person = new Person();
 - console.log(person.age); // 18
 
上述代码,实际等同于以下形式:
- Person = addAge(function Person() { ... });
 
上述可以看到,当装饰器作为修饰类的时候,会把构造器传递进去。constructor.prototype.age 就是在每一个实例化对象上面添加一个 age 属性
同样,装饰器可以用于修饰类的方法,这时候装饰器函数接收的参数变成了:
可以看到,这三个属性实际就是Object.defineProperty的三个参数,如果是类的属性,则没有传递第三个参数
如下例子:
- // 声明装饰器修饰方法/属性
 - function method(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 - console.log(target);
 - console.log("prop " + propertyKey);
 - console.log("desc " + JSON.stringify(descriptor) + "\n\n");
 - descriptor.writable = false;
 - };
 - function property(target: any, propertyKey: string) {
 - console.log("target", target)
 - console.log("propertyKey", propertyKey)
 - }
 - class Person{
 - @property
 - name: string;
 - constructor() {
 - this.name = 'huihui';
 - }
 - @method
 - say(){
 - return 'instance method';
 - }
 - @method
 - static run(){
 - return 'static method';
 - }
 - }
 - const xmz = new Person();
 - // 修改实例方法say
 - xmz.say = function() {
 - return 'edit'
 - }
 
输出如下图所示:
接收3个参数,分别是:
- function logParameter(target: Object, propertyName: string, index: number) {
 - console.log(target);
 - console.log(propertyName);
 - console.log(index);
 - }
 - class Employee {
 - greet(@logParameter message: string): string {
 - return `hello ${message}`;
 - }
 - }
 - const emp = new Employee();
 - emp.greet('hello');
 
输入如下图:
使用起来方式与方法装饰一致,如下:
- function modification(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
 - console.log(target);
 - console.log("prop " + propertyKey);
 - console.log("desc " + JSON.stringify(descriptor) + "\n\n");
 - };
 - class Person{
 - _name: string;
 - constructor() {
 - this._name = 'huihui';
 - }
 - @modification
 - get name() {
 - return this._name
 - }
 - }
 
如果想要传递参数,使装饰器变成类似工厂函数,只需要在装饰器函数内部再函数一个函数即可,如下:
- function addAge(age: number) {
 - return function(constructor: Function) {
 - constructor.prototype.age = age
 - }
 - }
 - @addAge(10)
 - class Person{
 - name: string;
 - age!: number;
 - constructor() {
 - this.name = 'huihui';
 - }
 - }
 - let person = new Person();
 
当多个装饰器应用于一个声明上,将由上至下依次对装饰器表达式求值,求值的结果会被当作函数,由下至上依次调用,例如如下:
- function f() {
 - console.log("f(): evaluated");
 - return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
 - console.log("f(): called");
 - }
 - }
 - function g() {
 - console.log("g(): evaluated");
 - return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
 - console.log("g(): called");
 - }
 - }
 - class C {
 - @f()
 - @g()
 - method() {}
 - }
 - // 输出
 - f(): evaluated
 - g(): evaluated
 - g(): called
 - f(): called
 
可以看到,使用装饰器存在两个显著的优点:
代码可读性变强了,装饰器命名相当于一个注释
在不改变原有代码情况下,对原来功能进行扩展
后面的使用场景中,借助装饰器的特性,除了提高可读性之后,针对已经存在的类,可以通过装饰器的特性,在不改变原有代码情况下,对原来功能进行扩展
参考文献
https://www.tslang.cn/docs/handbook/decorators.html
https://juejin.cn/post/6844903876605280269#heading-5
                文章名称:面试官:说说你对TypeScript中装饰器的理解?应用场景?
                
                浏览路径:http://www.csdahua.cn/qtweb/news14/121464.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网