成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:說說你對 TypeScript 中裝飾器的理解?應用場景?

開發 前端
裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法, 訪問符,屬性或參數上,是一種在不改變原類和使用繼承的情況下,動態地擴展對象功能。

[[423007]]

一、是什么

裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法, 訪問符,屬性或參數上

是一種在不改變原類和使用繼承的情況下,動態地擴展對象功能

同樣的,本質也不是什么高大上的結構,就是一個普通的函數,@expression 的形式其實是Object.defineProperty的語法糖

expression求值后必須也是一個函數,它會在運行時被調用,被裝飾的聲明信息做為參數傳入

二、使用方式

由于typescript是一個實驗性特性,若要使用,需要在tsconfig.json文件啟動,如下:

  1.     "compilerOptions": { 
  2.         "target""ES5"
  3.         "experimentalDecorators"true 
  4.     } 

typescript裝飾器的使用和javascript基本一致

類的裝飾器可以裝飾:

  • 方法/屬性
  • 參數
  • 訪問器
  • 類裝飾

例如聲明一個函數 addAge 去給 Class 的屬性 age 添加年齡.

  1. function addAge(constructor: Function) { 
  2.   constructor.prototype.age = 18; 
  3.  
  4. @addAge 
  5. class Person{ 
  6.   name: string; 
  7.   age!: number; 
  8.   constructor() { 
  9.     this.name = 'huihui'
  10.   } 
  11.  
  12. let person = new Person(); 
  13.  
  14. console.log(person.age); // 18 

上述代碼,實際等同于以下形式:

  1. Person = addAge(function Person() { ... }); 

上述可以看到,當裝飾器作為修飾類的時候,會把構造器傳遞進去。constructor.prototype.age 就是在每一個實例化對象上面添加一個 age 屬性

方法/屬性裝飾

同樣,裝飾器可以用于修飾類的方法,這時候裝飾器函數接收的參數變成了:

  • target:對象的原型
  • propertyKey:方法的名稱
  • descriptor:方法的屬性描述符

可以看到,這三個屬性實際就是Object.defineProperty的三個參數,如果是類的屬性,則沒有傳遞第三個參數

如下例子:

  1. // 聲明裝飾器修飾方法/屬性 
  2. function method(target: any, propertyKey: string, descriptor: PropertyDescriptor) { 
  3.   console.log(target); 
  4.   console.log("prop " + propertyKey); 
  5.   console.log("desc " + JSON.stringify(descriptor) + "\n\n"); 
  6.   descriptor.writable = false
  7. }; 
  8.  
  9. function property(target: any, propertyKey: string) { 
  10.   console.log("target", target) 
  11.   console.log("propertyKey", propertyKey) 
  12.  
  13. class Person{ 
  14.  @property 
  15.  name: string; 
  16.  constructor() { 
  17.    this.name = 'huihui'
  18.  } 
  19.  
  20.  @method 
  21.  say(){ 
  22.    return 'instance method'
  23.  } 
  24.  
  25.  @method 
  26.  static run(){ 
  27.    return 'static method'
  28.  } 
  29.  
  30. const xmz = new Person(); 
  31.  
  32. // 修改實例方法say 
  33. xmz.say = function() { 
  34.  return 'edit' 

輸出如下圖所示:

參數裝飾

接收3個參數,分別是:

  • target :當前對象的原型
  • propertyKey :參數的名稱
  • index:參數數組中的位置
  1. function logParameter(target: Object, propertyName: string, index: number) { 
  2.   console.log(target); 
  3.   console.log(propertyName); 
  4.   console.log(index); 
  5.  
  6. class Employee { 
  7.   greet(@logParameter message: string): string { 
  8.       return `hello ${message}`; 
  9.   } 
  10. const emp = new Employee(); 
  11. emp.greet('hello'); 

輸入如下圖:

訪問器裝飾

使用起來方式與方法裝飾一致,如下:

  1. function modification(target: Object, propertyKey: string, descriptor: PropertyDescriptor) { 
  2.   console.log(target); 
  3.   console.log("prop " + propertyKey); 
  4.   console.log("desc " + JSON.stringify(descriptor) + "\n\n"); 
  5. }; 
  6.  
  7. class Person{ 
  8.  _name: string; 
  9.  constructor() { 
  10.    this._name = 'huihui'
  11.  } 
  12.  
  13.  @modification 
  14.  get name() { 
  15.    return this._name 
  16.  } 

裝飾器工廠

如果想要傳遞參數,使裝飾器變成類似工廠函數,只需要在裝飾器函數內部再函數一個函數即可,如下:

  1. function addAge(age: number) { 
  2.   return function(constructor: Function) { 
  3.     constructor.prototype.age = age 
  4.   } 
  5.  
  6. @addAge(10) 
  7. class Person{ 
  8.   name: string; 
  9.   age!: number; 
  10.   constructor() { 
  11.     this.name = 'huihui'
  12.   } 
  13.  
  14. let person = new Person(); 

執行順序

當多個裝飾器應用于一個聲明上,將由上至下依次對裝飾器表達式求值,求值的結果會被當作函數,由下至上依次調用,例如如下:

  1. function f() { 
  2.     console.log("f(): evaluated"); 
  3.     return function (target, propertyKey: string, descriptor: PropertyDescriptor) { 
  4.         console.log("f(): called"); 
  5.     } 
  6.  
  7. function g() { 
  8.     console.log("g(): evaluated"); 
  9.     return function (target, propertyKey: string, descriptor: PropertyDescriptor) { 
  10.         console.log("g(): called"); 
  11.     } 
  12.  
  13. class C { 
  14.     @f() 
  15.     @g() 
  16.     method() {} 
  17.  
  18. // 輸出 
  19. f(): evaluated 
  20. g(): evaluated 
  21. g(): called 
  22. f(): called 

三、應用場景

可以看到,使用裝飾器存在兩個顯著的優點:

代碼可讀性變強了,裝飾器命名相當于一個注釋

在不改變原有代碼情況下,對原來功能進行擴展

后面的使用場景中,借助裝飾器的特性,除了提高可讀性之后,針對已經存在的類,可以通過裝飾器的特性,在不改變原有代碼情況下,對原來功能進行擴展

參考文獻

https://www.tslang.cn/docs/handbook/decorators.html

 

https://juejin.cn/post/6844903876605280269#heading-5

 

責任編輯:武曉燕 來源: JS每日一題
相關推薦

2021-09-06 10:51:27

TypeScriptJavaScript

2021-09-16 07:52:18

算法應用場景

2021-09-08 07:49:34

TypeScript 泛型場景

2021-11-05 07:47:56

代理模式對象

2021-11-09 08:51:13

模式命令面試

2021-11-10 07:47:49

組合模式場景

2021-08-16 08:33:26

git

2021-11-03 14:10:28

工廠模式場景

2021-09-28 07:12:09

測試路徑

2021-11-11 16:37:05

模板模式方法

2021-11-22 23:50:59

責任鏈模式場景

2021-09-29 07:24:20

場景數據

2021-10-13 18:01:33

快速排序場景

2021-10-08 09:59:32

冒泡排序場景

2021-10-09 10:25:41

排序應用場景

2021-11-04 06:58:32

策略模式面試

2021-05-31 10:35:34

TCPWebSocket協議

2021-06-01 08:25:06

Node.jsJavaScript運行

2021-10-18 07:51:39

回溯算法面試

2021-10-11 09:38:41

開源
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美激情一区二区 | 成人免费看片 | 欧美日韩在线一区二区 | 性天堂网 | 99国产精品99久久久久久 | 久久久亚洲一区 | 亚洲一区网站 | 99免费在线 | 日一区二区 | 国产不卡一区 | 欧美在线观看一区 | 色综合一区二区 | 国产99久久精品一区二区永久免费 | 中文字幕在线观看成人 | 欧美一区视频 | 久草视频在线播放 | 国产亚洲一区二区三区在线观看 | 欧洲成人免费视频 | 青青草中文字幕 | 999精品在线 | 国产视频在线一区二区 | 成年女人免费v片 | 日韩色图视频 | 久久综合九色综合欧美狠狠 | 毛片一区二区三区 | 在线观看中文字幕一区二区 | 91se在线| 天天色图| 亚洲网站在线观看 | 欧美极品视频在线观看 | 国产精品久久国产精品 | 欧美日韩高清免费 | 国产ts人妖另类 | 国产成人在线视频播放 | 欧美啊v在线观看 | 日韩国产中文字幕 | 午夜三级网站 | 日韩欧美视频在线 | 毛片大全 | 国产成人精品一区二区三区网站观看 | 久久精品久久综合 |