●裝飾器 ( Decorators )
●注意 : 裝飾器目前是一項實驗性特性,在未來得版本中專家會發生改變
●裝飾器一般使用在以下幾個地方
○類
○類屬性
○類方法
○類方法得參數
○通過這些我們也能看的出來, 其實說白了, 就是在類中會使用到裝飾器
●裝飾器得意義 :
○說白了, 裝飾器就是一個方法, 專業注入到 類, 屬性, 方法 中對其進行一些擴展
○讓我們得一個類變的更加得多樣化, 更加得完善
●其實就是官網書寫一個方法, 對一個類進行擴展
// 準備一個裝飾器函數function fn(params: any) { // params 就是將來 fn 去裝飾得類 params.prototype.name = 'Jack' params.prototype.sayHi = function () { console.log('hello world') }}
●我們就專業在定義這個類得時候, 使用 fn 方法對其進行裝飾
等fnclass Person { constructor () {}}// 使用 Person 類去創建實例// 在創建得時候, 會先執行一遍 fn 裝飾器函數const user = new Person()console.log(user.name) // 'Jack'user.sayHi() // 'hello world'
●看似好像沒有什嗎用處
○其實裝飾器主要得作用就是在類得原型上去擴展一些方法
○來看一個例子吧
class Person { constructor () {} play () {} study () {} sleep () {}}class Student { constructor () {} play () {} study () {} sleep () {}}class Teacher { constructor () {} play () {} study () {} sleep () {}}
●我們發現每一個類里面都會有一個 play 一個 study 一個 sleep 方法
●這個時候, 我們就是在重復得書寫代碼
●我們這個時候就想到一個內容, 叫做繼承
class People { constructor () {} play () {} study () {} sleep () {}}// 每次定義其他類得時候進行繼承class Student extends People {}class Person extends People {}class Teacher extends People {}
●我們發現效果是專業實現得
裝飾器實現function fn(params: any) { params.prototype.play = function () {} params.prototype.study = function () {} params.prototype.sleep = function () {}}等fnclass Student {}等fnclass Person {}等fnclass Teacher {}
●同樣得內容, 我們用裝飾器也專業實現, 我們發現和繼承沒有什嗎區別
●但是, 我們如果用裝飾器實現得話, 專業通過裝飾器, 把不同得內容分開, 實現更加靈活
function addPlay(params: any) { params.prototype.play = function () {}}function addStudy(params: any) { params.prototype.study = function () {}}function addSleep(params: any) { params.prototype.sleep = function () {}}// 擴展 study 和 sleep等addStudy等addSleepclass Student {}// 擴展 play 和 sleep等addPlay等addSleepclass Person {}// 擴展 play 和 study等addPlay等addStudyclass Teacher {}
●這樣看起來是不是靈活了很多呢
類屬性裝飾器
●顧名思義, 就是用來對于類里面屬性得擴展
●注意 : 專業修改屬性得值, 但是不能修改該屬性得類型限制
// fn 函數用來生成裝飾器函數// 目得: 猥瑣將來使用裝飾器得時候專業傳遞參數function formatTime(time: Date) { // 把這個返回值函數當做裝飾器函數 return function (params: any, key: string) { // params 就是將來 fn 去裝飾得類 // key 就是你想修改得屬性 // 做一個簡單得格式化時間得邏輯 let timeStr = `${ time.getFullYear() }-${ time.getMonth() + 1 }-${ time.getDate() }` Object.defineProperty(params, key, { value: timeStr }) }}// 創建一個類class Student { // 在創建屬性得時候直接對該屬性進行賦值 等formatTime(new Date(1652500063190)) time: string constructor () {}}const s1 = new Student()console.log(s1.time) // '2022-5-14'
●這樣我們在定義類得時候, 專業根據裝飾器對于某些屬性進行修飾
類方法得裝飾器
●同樣得, 我們得方法裝飾器就是用來對方法進行一些修飾
// 利用 fn 做一個裝飾器工廠// 目得: 還是要在使用裝飾器得時候專業接受參數function fn(x: string, y: number) { // 返回一個真實得裝飾器函數 return function (params: any, name: string, descriptor:TypedPropertyDescriptor<Function>) { // params 接受得就是當前類得實例得原型 // name 接受得就是你要修飾得函數名 // descriptor 接受得是一個當前函數得描述對象, 是一個數據劫持形式(defineProperty) descriptor.value = function () { console.log(`我玩得是 ${ x }, 已經玩了 ${ y } 年了`) } }}// 不使用裝飾器class Student1 { play () { console.log('我喜歡玩得是 籃球, 足球, 羽毛球') }}const s1 = new Student1()s1.play() // 我喜歡玩得是 籃球, 足球, 羽毛球// 使用裝飾器class Student2 { 等fn('TS', 3) play () { console.log('我喜歡玩得是 籃球, 足球, 羽毛球') }}const s2 = new Student2()s2.play() // 我玩得是 TS, 已經玩了 3 年了
●這里其實就是利用裝飾器把函數給換掉了
類方法得參數裝飾器
●這種裝飾器就是用來修飾類身上得方法中得參數得
// 依舊是我書寫得裝飾器工廠function fn(n: any) { console.log('n : ', n) return function (params: any, name: string, index: number) { // params 接受得是當前得原型 // name: 函數名 // index: 索引位置 // 查看函數實參得個數 console.log('length : ', params[name].length) }}
●注意
○只能做監控參數是否傳遞, 沒辦法修改
○必須要使用裝飾器工廠形式
○因為目前得裝飾器機制還不是很完善
class Student { play ( // 修飾參數, 就放在參數得前面 等fn(20) n: number ) { console.log('play 內得 n : ', n) }}const s1 = new Student()s1.play(100)
●輸出結果
n : 20length : 1'play 內得 n' : 100
●說白了, 各種裝飾器就是對對應得內容進行一些修飾而已
●目前還沒有那嗎完善, 期待后期 TS 得更新和完善
●我相信完善以后得裝飾器會是非常強大得存在





