自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:說(shuō)說(shuō)你對(duì) TypeScript 中裝飾器的理解?應(yīng)用場(chǎng)景?

開(kāi)發(fā) 前端
裝飾器是一種特殊類(lèi)型的聲明,它能夠被附加到類(lèi)聲明,方法, 訪問(wèn)符,屬性或參數(shù)上,是一種在不改變?cè)?lèi)和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展對(duì)象功能。

[[423007]]

一、是什么

裝飾器是一種特殊類(lèi)型的聲明,它能夠被附加到類(lèi)聲明,方法, 訪問(wèn)符,屬性或參數(shù)上

是一種在不改變?cè)?lèi)和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展對(duì)象功能

同樣的,本質(zhì)也不是什么高大上的結(jié)構(gòu),就是一個(gè)普通的函數(shù),@expression 的形式其實(shí)是Object.defineProperty的語(yǔ)法糖

expression求值后必須也是一個(gè)函數(shù),它會(huì)在運(yùn)行時(shí)被調(diào)用,被裝飾的聲明信息做為參數(shù)傳入

二、使用方式

由于typescript是一個(gè)實(shí)驗(yàn)性特性,若要使用,需要在tsconfig.json文件啟動(dòng),如下:

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

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

類(lèi)的裝飾器可以裝飾:

  • 類(lèi)
  • 方法/屬性
  • 參數(shù)
  • 訪問(wèn)器
  • 類(lèi)裝飾

例如聲明一個(gè)函數(shù) 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 

上述代碼,實(shí)際等同于以下形式:

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

上述可以看到,當(dāng)裝飾器作為修飾類(lèi)的時(shí)候,會(huì)把構(gòu)造器傳遞進(jìn)去。constructor.prototype.age 就是在每一個(gè)實(shí)例化對(duì)象上面添加一個(gè) age 屬性

方法/屬性裝飾

同樣,裝飾器可以用于修飾類(lèi)的方法,這時(shí)候裝飾器函數(shù)接收的參數(shù)變成了:

  • target:對(duì)象的原型
  • propertyKey:方法的名稱(chēng)
  • descriptor:方法的屬性描述符

可以看到,這三個(gè)屬性實(shí)際就是Object.defineProperty的三個(gè)參數(shù),如果是類(lèi)的屬性,則沒(méi)有傳遞第三個(gè)參數(shù)

如下例子:

  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. // 修改實(shí)例方法say 
  33. xmz.say = function() { 
  34.  return 'edit' 

輸出如下圖所示:

參數(shù)裝飾

接收3個(gè)參數(shù),分別是:

  • target :當(dāng)前對(duì)象的原型
  • propertyKey :參數(shù)的名稱(chēng)
  • index:參數(shù)數(shù)組中的位置
  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'); 

輸入如下圖:

訪問(wèn)器裝飾

使用起來(lái)方式與方法裝飾一致,如下:

  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.  } 

裝飾器工廠

如果想要傳遞參數(shù),使裝飾器變成類(lèi)似工廠函數(shù),只需要在裝飾器函數(shù)內(nèi)部再函數(shù)一個(gè)函數(shù)即可,如下:

  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(); 

執(zhí)行順序

當(dāng)多個(gè)裝飾器應(yīng)用于一個(gè)聲明上,將由上至下依次對(duì)裝飾器表達(dá)式求值,求值的結(jié)果會(huì)被當(dāng)作函數(shù),由下至上依次調(diào)用,例如如下:

  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 

三、應(yīng)用場(chǎng)景

可以看到,使用裝飾器存在兩個(gè)顯著的優(yōu)點(diǎn):

代碼可讀性變強(qiáng)了,裝飾器命名相當(dāng)于一個(gè)注釋

在不改變?cè)写a情況下,對(duì)原來(lái)功能進(jìn)行擴(kuò)展

后面的使用場(chǎng)景中,借助裝飾器的特性,除了提高可讀性之后,針對(duì)已經(jīng)存在的類(lèi),可以通過(guò)裝飾器的特性,在不改變?cè)写a情況下,對(duì)原來(lái)功能進(jìn)行擴(kuò)展

參考文獻(xiàn)

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

 

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

 

責(zé)任編輯:武曉燕 來(lái)源: JS每日一題
相關(guān)推薦

2021-09-06 10:51:27

TypeScript類(lèi)JavaScript

2021-09-16 07:52:18

算法應(yīng)用場(chǎng)景

2021-09-08 07:49:34

TypeScript 泛型場(chǎng)景

2021-11-10 07:47:49

組合模式場(chǎng)景

2021-11-03 14:10:28

工廠模式場(chǎng)景

2021-08-16 08:33:26

git

2021-11-09 08:51:13

模式命令面試

2021-11-05 07:47:56

代理模式對(duì)象

2021-09-29 07:24:20

場(chǎng)景數(shù)據(jù)

2021-09-28 07:12:09

測(cè)試路徑

2021-11-11 16:37:05

模板模式方法

2021-11-22 23:50:59

責(zé)任鏈模式場(chǎng)景

2021-10-09 10:25:41

排序應(yīng)用場(chǎng)景

2021-10-08 09:59:32

冒泡排序場(chǎng)景

2021-10-13 18:01:33

快速排序場(chǎng)景

2021-11-04 06:58:32

策略模式面試

2021-05-31 10:35:34

TCPWebSocket協(xié)議

2021-10-18 07:51:39

回溯算法面試

2021-10-12 07:15:02

歸并排序場(chǎng)景

2021-10-11 09:38:41

開(kāi)源
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)