精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

探索TypeScript:裝飾器

開發 前端
函數最后都會返回r?對象,一開始會給予實參個數以及特定參數進行判斷處理,然后基于decorators、target獲得所有裝飾方法,然后拿到裝飾類的原型。

前言

最近在學習Nest.js的內容,發現裝飾器本質和Java的面向切面編程。裝飾器用于給類,方法,屬性以及方法參數等增加一些附屬功能而不影響其原有特性。其在Typescript應用中的主要作用類似于Java中的注解,在AOP(面向切面編程)使用場景下非常有用。

面向切面編程(AOP)  是一種編程范式,它允許我們分離橫切關注點,藉此達到增加模塊化程度的目標。它可以在不修改代碼自身的前提下,給已有代碼增加額外的行為(通知)

裝飾器一般用于處理一些與類以及類屬性本身無關的邏輯,例如: 一個類方法的執行耗時統計或者記錄日志,可以單獨拿出來寫成裝飾器。

看一下官方的解釋更加清晰明了

裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法, 訪問符,屬性或參數上。 裝飾器使用 @expression這種形式,expression求值后必須為一個函數,它會在運行時被調用,被裝飾的聲明信息做為參數傳入。

如果有使用過spring boot或者php的symfony框架的話,就基本知道裝飾器的作用分別類似于以上兩者注解和annotation,而node中裝飾器用的比較好的框架是nest.js。不過不了解也沒關系,接下來我就按我的理解講解一下裝飾器的使用。

不過目前裝飾器還不屬于標準,還在建議征集的第二階段,但這并不妨礙我們在ts中的使用。只要在 tsconfig.json中開啟 experimentalDecorators就可以使用了。

{  
    "compilerOptions": {  
        "target": "ES5",  
        "experimentalDecorators": true  
    }  
}

類裝飾器

類裝飾器僅接受一個參數,該參數表示類本身。

同時,如果類裝飾器返回一個值,它會使用提供的構造函數來替換類的聲明。

比如:

// 類裝飾器,接受一個參數即為類本身
// 將裝飾后的類以及類的原型全部凍結變為不可擴展以及不可修改
function freeze(constructor: Function) {
  Object.freeze(constructor); // 凍結裝飾的類
  Object.freeze(constructor.prototype); // 凍結類的原型
}


// 調用 freeze 裝飾裝飾 BugReport
@freeze
class BugReport {
  static type = 'report'
}


BugReport.type = 'hello'
console.log(BugReport.type) // TypeError: Cannot assign to read only property 'type' of function 'class BugReport

同時類裝飾器如果存在一個有效返回值,該返回值會替代被修飾類的構造函數返回的實例對象。比如:

function override(target: new () => any) {
  return class Child {

  }
}

@override // override 裝飾器修改了 Parent class 返回的實例對象
class Parent {

}

const instance = new Parent()

console.log(instance) // Child {}

方法裝飾器

方法裝飾器是在方法聲明之前聲明的。方式裝飾器可用于觀察、修改或替換方法定義。

方法裝飾器接受三個參數:

  • 如果該裝飾器修飾的是類的靜態方法,那么第一個參數表示當前類的構造函數(即當前類)。如果修飾為類的原型方式,那么第一個參數表示該類的原型對象(prototype)。
  • 第二個參數表示該方法參數器修改的類的名稱。
  • 第三個參數表示當前方法的屬性描述符。

同時,如果方法裝飾器返回一個值,它會被用作方法的屬性描述符。

比如下面的例子,我們使用方法裝飾器修改類的實例方法,將 greet 方法變為不可枚舉:

function enumerable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {

    console.log(target) // Greeter.prototype
    console.log(propertyKey) // greet

    // 將該方法(Greeter.prototype.greet) 變為不可枚舉
    descriptor.enumerable = value;
  };
}


class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
 
  // @enumerable(false) 修飾實例方法,既修飾器第一個參數為 Greeter.prototype
  @enumerable(false)
  greet() {
    return "Hello, " + this.greeting;
  }
}

console.log(Object.keys(Greeter.prototype)) // []

屬性訪問器裝飾器

屬性訪問器裝飾器同樣在屬性訪問器聲明前使用,常用于觀察、修改或替換屬性訪問器的定義。

當屬性裝飾器被調用時,和方法裝飾器同樣會接受三個參數,分別為:

  • 如果當前屬性訪問器為類的靜態屬性訪問器,那么屬性訪問器修飾器接受的第一個參數則為當前類的構造函數。否則,如果修飾的為實例上的屬性訪問器,則第一個參數為類的原型。
  • 第二個參數為當前被修飾的成員名稱。
  • 第三個參數為當前被修飾的屬性描述符。

同樣,如果訪問器裝飾器返回一個值,它也會被用作方法的屬性描述符。

比如,當我們使用裝飾器來修飾當前類上的屬性訪問器時:

function baseLog(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  // 觸發屬性訪問器時
  console.log(`Trigger getter(${target.name}/${propertyKey})`)
}

class Person {

  @baseLog
  static get username() {
    return '19Qingfeng'
  }
}

// Trigger getter(Person/username)
// 19Qingfeng
console.log(Person.username)

參數裝飾器

同樣,class 上每個方法的參數還存在參數修飾器。參數修飾器會為參數聲明之前,同樣具有三個參數:

  • 當參數修飾器修飾的所在方法為類的構造函數/靜態方法時,第一個參數表示類的構造函數(類本身)。反之,當參數修飾器修飾的參數所在的方法為實例方法時,此時第一個參數代表類的原型。
  • 如果修飾的為類的靜態/實例方法時,第二個參數為當前參數修飾器所在方法的方法名。如果參數修飾器所在的方法為類的構造函數參數修飾時,此時第二個參數為 undefined。
  • 第三個參數,表示當前參數所在方法的位置索引。

我們依次來看看參數裝飾器分別裝飾類的構造函數、類的靜態方法上的參數以及類的實例方法上的參數不同表現:

參數修飾器所在方法為修飾類的構造函數:

class Person {

  constructor(@logger name: string) {

  }
}


function logger(target: any, methodName: string | undefined, index: number) {
  console.log(target) // [Function: Person]
  console.log(methodName) // undefined
  console.log(index) // 0
}

至此所有常見的類裝飾器都介紹完了,其實本質的裝飾器函數入參都是一致的,第一個參數是裝飾器所在的類名、第二個參數是裝飾參數,接下來我們看一下裝飾器的實現原理。

實現原理

我們將一個包含很多裝飾器的類將ts代碼編譯成es5的打包結果如下:

// ....
// 屬性裝飾器
__decorate([propertyDecorators], Parent.prototype, 'company', undefined);
// 訪問器屬性裝飾器(原型)
__decorate([accessorDecorator], Parent.prototype, 'gender', null);
// 方法裝飾器 & 參數(實例方法)裝飾器
__decorate(
  [methodDecorator, __param(0, paramDecorator)],
  Parent.prototype,
  'getName',
  null
);
// 訪問器屬性裝飾器(實例)
__decorate([accessorDecorator], Parent, 'staticGender', null);
// 方法裝飾器(實例)
__decorate([methodDecorator], Parent, 'getStaticName', null);
// 類裝飾器 & 參數裝飾器(類的構造函數)
Parent = __decorate([logger, __param(0, paramDecorator)], Parent);
return Parent;

會發現所有裝飾器都在調用__decorate方法,并且不同的裝飾器,對于__decorate方法的入參也是通用型很強。

  • 第一個參數表示當前修飾器個數的集合,這是一個數組。
  • 第二個參數表示當前修飾器修飾的目標(類的構造函數或者類的原型),這一步在 TS 編譯后就已經確定。
  • 第三個參數如果存在的話,表示當前修飾器修飾對象的 key (這是一個字符串,可能為方法名、屬性名等)。
  • 第四個參數如果存在的話,為 null 或者為 undefined。

然后我們再看一下具體的__decorate方法:

var __decorate = function (decorators, target, key, desc) {
 // 首先獲得實參的個數
 var c = arguments.length,

 // 1. 如果實參個數小于 3 ,則表示該裝飾器為 類裝飾或者在構造函數上的參數裝飾器
 // 2. 如果實參個數大于等于3, 則表示為非 1 情況的裝飾器。
 // 2.1 此時根據傳入的第四個參數,來判斷是否存在屬性描述
 // 如果 desc 傳入 null,則獲取當前 target key 的屬性描述符給 r 賦值。比如訪問器屬性裝飾器、方法裝飾器
 // 相反如果傳入非 null (通常為 undefined), 則直接返回 desc 。比如屬性裝飾器


 // 此時 r 根據不同情況,
 // 要么是傳入的 target    (實參個數小于3)
 // 要么是 Object.getOwnPropertyDescriptor(target, key) (實參個數小于3,且 desc 為 null)
 // 要么是 undefined (實參個數小于3, desc 為 undefined)
   r =
     c < 3
       ? target
       : desc === null
       ? (desc = Object.getOwnPropertyDescriptor(target, key))
       : desc,
   d;
 for (var i = decorators.length - 1; i >= 0; i--) {
   // 從數組的末尾到首部依次遍歷獲得每一個裝飾方法
   if ((d = decorators[i])) {
     // 同樣判斷參數個數
     // 1. 如果實參個數小于 3, 類裝飾器/構造函數上的參數裝飾
     // 此時 d 為當前裝飾器方法, r 為傳入的 target (Parent)
     // 此時直接使用當前裝飾器進行調用,傳入 d(r) 也就是 d(Parent)
     // 2. 如果實參個數大于 3 ,則調用當前裝飾 d(target, key, r)
     // 3. 如果實參個數等于 3 , 則調用 d(target, key)
     // 同時為 r 重新賦值,交給下一次 for 循環遍歷處理下一個裝飾器函數
     r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
   }
 }
 // 最終裝飾器函數會進行返回
 // 如果個數大于 3,并且 r 存在 則會返回 Object.defineProperty(target, key, r) ,將返回的 r 當作屬性描述符定義在 target key 上
 // 最終返回 r 
 return c > 3 && r && Object.defineProperty(target, key, r), r;
};

函數最后都會返回r對象,一開始會給予實參個數以及特定參數進行判斷處理,然后基于decorators、target獲得所有裝飾方法,然后拿到裝飾類的原型。

最終,會返回處理后的裝飾器方法 r,在類裝飾器上我們會使用到返回后的 r 重新賦值給當前構造函數。

Parent = __decorate([logger, __param(0, paramDecorator)], Parent);

至此,深入淺出裝飾器全過程結束。

責任編輯:武曉燕 來源: 量子前端
相關推薦

2023-08-07 16:07:42

2022-09-26 09:02:54

TS 裝飾器TypeScript

2022-05-10 09:12:16

TypeScript裝飾器

2021-06-17 09:32:17

前端TypeScript 技術熱點

2025-04-07 04:00:00

AngularTypeScript裝飾器

2023-07-12 08:29:58

TypeScrip元組元素

2023-02-07 07:47:52

Python裝飾器函數

2010-02-01 17:50:32

Python裝飾器

2021-09-10 06:50:03

TypeScript裝飾器應用

2016-11-01 09:24:38

Python裝飾器

2022-09-19 23:04:08

Python裝飾器語言

2023-02-06 08:09:24

TypeScriptES裝飾器

2021-02-01 14:17:53

裝飾器外層函數里層函數

2017-07-07 17:01:32

裝飾器代碼Python

2021-06-01 07:19:58

Python函數裝飾器

2023-12-11 15:51:00

Python裝飾器代碼

2023-09-04 13:14:00

裝飾器設計模式

2024-05-24 11:36:28

Python裝飾器

2024-09-12 15:32:35

裝飾器Python

2020-04-13 16:05:25

JS裝飾器前端
點贊
收藏

51CTO技術棧公眾號

av天堂一区二区| 国产精品av免费观看| 中文在线字幕av| 91偷拍一区二区三区精品| 91精品欧美福利在线观看 | 特黄特色欧美大片| 欧美性极品少妇| 亚洲激情免费视频| 亚洲欧美日韩成人在线| 久久99精品国产麻豆不卡| 久久久久久亚洲精品中文字幕 | 日韩美一区二区| 久久免费大视频| 精品对白一区国产伦| 国产极品美女高潮无套久久久| 精品视频在线一区二区| 99久久久免费精品国产一区二区 | 影音欧美亚洲| 人妻与黑人一区二区三区| 日韩激情视频在线观看| 久久91精品国产| 国产jk精品白丝av在线观看| 日韩欧美激情电影| 欧美性大战久久| 精品少妇人欧美激情在线观看| av在线电影播放| 成人18精品视频| 91嫩草在线视频| 午夜精品免费观看| 91久久午夜| 美日韩精品免费观看视频| 亚洲天堂视频一区| 91蝌蚪精品视频| 91精品国产全国免费观看| 超碰av在线免费观看| wwww在线观看免费视频| 亚洲欧美另类在线| 亚洲激情一区二区三区| 三级av在线播放| 不卡一区二区三区四区| 亚洲最大的免费| 伊人久久亚洲综合| 久久婷婷激情| 欧美一级大片视频| 亚洲 欧美 视频| 国模 一区 二区 三区| 欧美精品一区在线播放| 免费黄色激情视频| 第九色区aⅴ天堂久久香| 亚洲欧美日韩爽爽影院| 天堂久久久久久| 国产精品极品在线观看| 日韩欧美精品在线| 下面一进一出好爽视频| 国产亚洲观看| 欧美一区二区三区性视频| 在线观看岛国av| 91丨精品丨国产| 91精品啪在线观看国产60岁| 亚洲精品在线网址| 国产一区二区三区亚洲综合| 91精品国产黑色紧身裤美女| 久久精品视频在线观看免费| 美女精品久久| 日韩精品一区二区在线| 欧美日韩一区二区区| 麻豆精品在线| 欧美精品一区二区三区久久久| 好吊操视频这里只有精品| www.神马久久| 亚洲精品二三区| 中文字幕av观看| 精品一区在线| 中文字幕精品网| 三级黄色免费观看| 欧美成人有码| 国内精品小视频| 久久久久亚洲av成人毛片韩| 日本亚洲免费观看| 成人免费视频网址| 免费观看国产视频| 久久亚洲私人国产精品va媚药| 日本亚洲导航| 成人在线免费看黄| 亚洲成人1区2区| 美女福利视频在线| 日韩电影精品| 日韩精品一区二区三区在线播放| 国产精品九九视频| 国产一区二区在线| 久久久国产成人精品| 日韩xxx高潮hd| 青青青爽久久午夜综合久久午夜| 91免费版网站入口| 天堂中文在线观看视频| 国产欧美一区二区精品性| 韩国黄色一级大片| 天堂av中文在线观看| 欧美日韩三级在线| 亚洲视频 中文字幕| 免费毛片在线不卡| 欧美日韩999| 神马久久久久久久 | 免费人成视频在线播放| 伦理一区二区| 精品国产一区av| 欧美特黄aaaaaa| 国产又黄又大久久| 人偷久久久久久久偷女厕| 最新av在线播放| 色综合咪咪久久| 青青草精品在线| 国产成人av| 国产69精品99久久久久久宅男| 天干夜夜爽爽日日日日| 高清在线不卡av| 亚洲国产日韩综合一区| 美女搞黄视频在线观看| 欧美一区二区三区在线| av免费播放网站| 国产亚洲精品久久久久婷婷瑜伽| 91啪国产在线| a天堂在线资源| 精品久久久免费| 日本人dh亚洲人ⅹxx| 第一sis亚洲原创| 欧美在线一级va免费观看| 亚洲精品成人区在线观看| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ原创 | 久久久成人的性感天堂| 中文字幕+乱码+中文| 99久久免费精品高清特色大片| 麻豆传媒网站在线观看| 亚洲国产天堂| 亚洲网在线观看| 国产成人精品网| 成人中文字幕合集| 国产性生活免费视频| 日韩毛片网站| 在线精品视频视频中文字幕| 国产成人无码一区二区在线播放| www.爱久久.com| 996这里只有精品| 麻豆视频久久| 色与欲影视天天看综合网| 国产精品无码久久av| 自拍av一区二区三区| 爱情岛论坛亚洲首页入口章节| 美女久久99| 国产精品999| 黄色av网站在线看| 91精品91久久久中77777| 国产jk精品白丝av在线观看| 丝袜a∨在线一区二区三区不卡| 精品不卡一区二区三区| 麻豆国产在线| 亚洲美女福利视频网站| 特级西西444www大精品视频免费看 | 97香蕉久久超级碰碰高清版| 污视频在线免费| 日韩欧美精品网址| a级片在线观看| 日韩电影在线一区| 亚洲欧洲精品一区二区| 国产一区二区三区国产精品| 久热在线中文字幕色999舞| av男人天堂网| 午夜久久久影院| 超碰97人人干| 免费在线观看日韩欧美| 懂色av一区二区三区四区五区| 国产95亚洲| 欧美高清在线观看| 亚洲色图欧美视频| 色系网站成人免费| 99久久久无码国产精品不卡| 国内成+人亚洲+欧美+综合在线| 中文字幕乱码免费| 精品视频在线你懂得| 日本欧美爱爱爱| 日本免费在线观看| 精品国产一区二区三区久久久蜜月 | 国产强伦人妻毛片| 亚洲一区二区三区四区中文字幕| 熟妇高潮精品一区二区三区| 久久亚洲欧美| 天天干天天操天天干天天操| 黄色欧美在线| 国产精品黄视频| 99热国产在线| 亚洲精品久久久一区二区三区| 日韩中文字幕高清| 亚洲乱码精品一二三四区日韩在线| a级片在线观看视频| 日韩有码一区二区三区| 亚洲小视频在线播放| 日本国产精品| 成人欧美一区二区三区在线| 成年人视频免费在线播放| 国产一区二区三区丝袜| 精品人妻一区二区三区浪潮在线 | 国产成人一级电影| 无码人妻h动漫| 一本精品一区二区三区| 蜜桃999成人看片在线观看| 91嫩草国产线观看亚洲一区二区| 国产91精品久久久久久久| 亚洲图片88| 亚洲国产中文字幕在线观看| 一区不卡在线观看| 欧美性猛交xxxx免费看| 青青青在线视频| 欧美高清在线视频| 国产精品一级黄片| 国产精品18久久久久久vr| 狠狠操精品视频| 尤物网精品视频| 中文字幕乱码免费| 成人一区不卡| 久久久久久久有限公司| 亚洲视频国产精品| 成人免费大片黄在线播放| 婷婷六月国产精品久久不卡| 国内精品久久久久久| 国产在线观看av| 亚洲天堂免费在线| 日韩一二三四| 欧美mv日韩mv国产网站| 91禁在线观看| 欧美探花视频资源| 国产精品久久久久久人| 精品国产乱码久久久久酒店| 毛片a片免费观看| 亚洲久草在线视频| 欧美h片在线观看| 国产日韩av一区二区| 极品粉嫩小仙女高潮喷水久久| 成人午夜精品在线| 极品人妻一区二区| 国产精品资源网站| 中文国产在线观看| 精品在线播放免费| 91精品999| 久久精品99久久久| 蜜臀av免费观看| 美女视频免费一区| 亚洲天堂网一区| 久久精品久久99精品久久| 国产wwwxx| 欧美专区在线| 免费看a级黄色片| 日韩精品国产欧美| 欧美日韩亚洲自拍| 久久成人精品无人区| 午夜免费看毛片| 久久99国产精品尤物| 一本一道久久a久久综合蜜桃| 美女视频一区二区三区| 色18美女社区| 国产精品亚洲人在线观看| 青青草精品在线| 99久久亚洲一区二区三区青草 | 一级爱爱免费视频| 欧美日本一区二区三区| 国产精品玖玖玖| 日韩欧美一区在线| 日本黄色三级视频| 日韩av影视综合网| 国产日韩精品在线看| 中文字幕在线国产精品| 中文字幕中文字幕在线十八区 | 亚洲第一区在线观看| 亚洲日本香蕉视频| 自拍视频国产精品| 性欧美ⅴideo另类hd| 91精品国产精品| 亚洲伦乱视频| 91丝袜美腿美女视频网站| 这里视频有精品| 久久这里精品国产99丫e6| 精品视频亚洲| 免费日韩在线观看| 欧美综合二区| 久久久久久综合网| 波多野结衣中文字幕一区二区三区| 精品无码人妻一区| 中文字幕在线播放不卡一区| 国产一级片视频| 在线日韩av片| 精品国产一级片| 精品一区二区三区四区| 国产不卡在线| 欧美亚洲国产日本| av在线播放一区二区| 国产自产精品| 97精品视频在线看| 免费在线观看亚洲视频| 男人的天堂久久精品| 欧美图片自拍偷拍| 欧美激情综合在线| 国产精品第一页在线观看| 欧美曰成人黄网| 日韩一级片免费看| 久久综合免费视频影院| 二区三区不卡| 豆国产97在线| 色88久久久久高潮综合影院| 欧美日韩二三区| 国产999精品久久久久久| 蜜桃av乱码一区二区三区| 亚洲国产欧美在线人成| 在线免费观看av片| 亚洲国产97在线精品一区| 毛片在线看网站| 日韩免费中文字幕| 精品国内亚洲2022精品成人| 国产精品h视频| 日韩影院精彩在线| 少妇饥渴放荡91麻豆| 一区二区日韩电影| 一区二区不卡视频在线观看| 亚洲欧美中文字幕在线一区| 国产www视频在线观看| 91精品免费视频| 欧美综合久久| 国产在线观看福利| 99久久伊人网影院| 国产一级大片在线观看| 欧美一区二区三区在线看| 中文字幕在线播放| 国产精品久久久久久久久久免费 | 日韩av电影免费在线| 99riav国产精品| 深夜视频在线观看| 一区二区三区四区在线| 国产又粗又猛又爽又黄91| 中文字幕日韩精品在线观看| 韩日精品一区二区| 九色91视频| 亚洲永久免费精品| 国产精品久久久免费观看| 亚洲成人黄色影院| 欧美特黄一级视频| 97色伦亚洲国产| 久久超级碰碰| 天堂…中文在线最新版在线| 粉嫩久久99精品久久久久久夜| 免费看一级一片| 欧美www视频| xxx.xxx欧美| 国产一区二区在线网站| 一区二区精品| 右手影院亚洲欧美| 欧美视频在线免费| 国产日韩精品在线看| 国产精品一区二区久久| 99精品在线观看| 日韩av影视大全| 一个色妞综合视频在线观看| 高清国产mv在线观看| 久久人91精品久久久久久不卡| xxxx日韩| 日韩中文字幕二区| 日本一区二区三级电影在线观看| 中文字幕永久在线视频| 日韩视频免费在线| 91欧美极品| 不卡影院一区二区| 国产精品久久久久影院老司| 国产精品乱码久久久| 欧美精品video| 天海翼亚洲一区二区三区| mm1313亚洲国产精品无码试看| 国产精品久久久久婷婷二区次| 国产精品欧美亚洲| 久久久免费在线观看| 自拍自偷一区二区三区| 亚洲美女爱爱视频| 亚洲成人精品一区| 成人77777| 99理论电影网| 久久高清国产| 好吊日在线视频| 精品亚洲一区二区三区在线播放| av在线不卡精品| 久久久久久久久久久综合| 91麻豆swag| 国产精品国产三级国产aⅴ | 深夜福利影院在线观看| 亚洲精品久久7777777| 玖玖精品在线| av日韩一区二区三区| 国产女主播一区| 午夜久久久久久久久久| 日韩av电影在线播放| 亚洲精品一二三区区别| 性久久久久久久久久| 91麻豆精品国产自产在线| 黄色漫画在线免费看| 宅男av一区二区三区|