TypeScript徹底解讀(26課時)_17.裝飾器


實驗性的特性,須要在tslint裏面把這項設置爲true

做用域類的聲明方法、訪問符、屬性和參數上
使用@符號加一個名字來定義,名字必須是一個函數,或者求值後是一個函數

裝飾器工廠,setPro當作一個裝飾器工廠,裏面返回一個函數的結果。
調用的時候直接@setProp() 後面加上括號去調用

裝飾器組合使用,裝飾器工廠是從上往下調用,普通的裝飾器是從下往上一次執行

若是都是裝飾器工廠,就是從上向下執行,依次就出來裝飾器工廠內的值

定義兩個裝飾器工廠

  在類的上面加上裝飾器的工廠,從上到下執行裝飾器工廠,求完值以後,再從後往前執行這個裝飾器邏輯瀏覽器

類裝飾器在類聲明以前聲明函數


判斷sign是否是等於類ClassDec

sign是否等於原型對象上的構造函數,也是true

判斷相等說明他們是同一個對象,經過裝飾器,咱們能夠修改類的遠行對象或構造函數



因此咱們要定義文件接口經過聲明合併來解決這個問題
在ClassD後面定義一個接口叫作ClassD和類ClassD的名字相同。這樣classD就有了name屬性了。

這樣就打印出了類的屬性,經過裝飾器把name屬性修改爲了name

使用了。同名的 接口和同名的類,進行聲明合併之後,name添加到了類的原型對象上,因此咱們也能夠拿到它的值
若是類裝飾器返回一個值,那麼會使用這個返回的值替代被裝飾的類的聲明,因此咱們使用這個特性去修改類的實現。可是要注意的是咱們要本身處理咱們的原型鏈
能夠經過裝飾器來覆蓋類裏面的一些操做,能夠看一下官方的一個例子



es5

14分53秒
首先定義一個裝飾器,給它使用一個泛型,而且進行約束,它是一個類, 構造函數,接收任意多的參數,返回值是一個對象


接收一個target參數

返回一個class定義,繼承target構造函數 這個類,在這個實例上添加兩個屬性,一個是NewProperty 一個是hello

定義好裝飾器工廠,接下來來定義一個類,也在類上添加兩個屬性

在類Greeter前面使用裝飾器,這裏是裝飾器而不是裝飾器工廠

裝飾器返回了一個類,而且是繼承了被修飾的這個類,target就是指的被修飾的類


給這個類傳一個world字符串

裝飾器返回的是一個類,這個類又繼承了被修飾的類,裝飾器返回的這個類會替換被裝飾的類的聲明,全部新建立的這個類既包含原來類的屬性,又包含了新定義的屬性,使用新的類替換了這個類以後,Greeter就是這兩個雷結合以後的類

修改裝飾器,返回的類再也不繼承被修飾的類對象

方法裝飾器

用來處理類中的方法,能夠處理方法的屬性描述符,方法的定義,在運行的時候也是被當作函數調用的
,包含三個參數,分兩種狀況,第一個若是裝飾的是靜態成員的狀況,參數表明的就是類的構造函數,若是裝飾的是實例成員的時候,參數1就是累的原型對象
參數2是成員的名字
參數3是成員的屬性描述符
先來補充一個js的知識,屬性裝飾符。對象能夠設置屬性,若是屬性值是函數,那麼這個函數成爲方法,每個屬性和方法在定義的時候都伴隨三個示例描述符
分別表明可配置、可寫、可枚舉

要修改屬性描述符他要用es5有的Object.defineProperty 方法,參數1是咱們建立的UI對象,參數2你要處理的屬性名或方法名,參數3就是對象用來設置屬性描述符,
它有四個值,第一個值是Value:也就是咱們要給這個屬性設置的名字,能夠是實際的字符串或者number類型的值,也開始是一個函數,若是你設置爲一個函數呢,這個屬性就稱之爲方法
如今先設置爲一個字符串的值,

第二設置可寫性,設置爲false那麼就是不可寫的

可配置的,可枚舉的

輸出,上面就有個name屬性

訪問下它的name值,提示不存在


因此先給他指定類型,定義一個接口

由於設置了可寫性是false,因此這裏修改了name的值再去打印出來仍是原來的值



可枚舉關閉後,for循環這個對象,裏面什麼也輸出不了

定義的時候默認加一個age屬性,就能夠輸出了,由於咱們經過defineProperty設置的是name屬性

可枚舉屬性打開,就能夠輸出name的值

可配置型

在上面先設置了name屬性,可寫性爲false,看配置型爲false
下面又定義了一遍name屬性,設置可寫行爲true,可是就報錯了 不能重複定義。
可配置性是不可逆的操做,若是期初設置了可配置性爲false,後續就不能再經過deineProperty去修改屬性修飾符了


方法裝飾器對於屬性描述符的相關操做,全部不支持es5的瀏覽器沒法支持屬性描述符
定義一個裝飾器
description.enumerable=bool表示設置屬性描述符
propertyName是方法的名字

第三個參數是一個對象,包含了三個屬性描述符


getAge方法上用裝飾器

當方法裝飾器裝飾的是靜態成員時,是構造函數,裝飾的是實例成員時是類的原型對象,還有類的原型對象上定義的方法它的target也是類的原型對象
打印出的target就是被修飾的類的構造函數

propertyName是方法的名字


第三個參數:PropertyDescruotionMap

定義了他的接口,有三個可選值,還有屬性值value

這裏直接修改它的屬性值,是否可枚舉就能夠了

遍歷它的值,只遍歷到了age屬性

可枚舉設置爲true,不光是有age,繼承過來的getAge也打印出來了

就是這個方法裝飾器,就能夠控制方法或者屬性的可枚舉性
若是方法裝飾器返回一個值,那麼就會用這個值做爲方法的屬性描述符對象,也就是至關於下面這個

修改這個裝飾器:

再加一個返回值類型爲any

建立實例後調用getAge方法

這是由於方法裝飾器返回的值,他會用這個值做爲這個屬性描述符對象,作一個替換

經過方法裝飾器,便可以修改方法或者屬性的屬性的屬性描述符的值,還能夠直接替換他的實現,這裏仍是要提醒一下,當構建目標小於es5的時候,方法裝飾器的返回值會被忽略blog

訪問器裝飾器

也就是以前講的get和set存取值函數,一個在設置屬性值的時候觸發,一個在獲取屬性值的時候觸發
ts不容許同時裝飾成員的get和set訪問器

訪問器裝飾器也有三個參數,這個三個參數和方法裝飾器是如出一轍的




定義name 的存取器

在get上面加裝飾器

不能同時給get和set同時加裝飾器

建立實例,打印實例的屬性,打印出來的只有下劃線name

若是去掉裝飾器,既有下劃線name也有name

若是設置了裝飾器爲true一樣也是兩個值繼承

屬性裝飾器

聲明在屬性的聲明以前,有兩個參數,和方法裝飾器的前兩個參數是同樣的,就是沒有屬性描述符對象。
屬性裝飾器無法操做屬性的屬性描述符,只能判斷某個類中是否聲明瞭某個名字的屬性

參數1被修飾的目標,參數2屬性名。這裏直接打印了屬性名

給的屬性name使用了裝飾器
索引

參數裝飾器

也有三個參數,前兩個和方法裝飾器是同樣的。
參數1:裝飾靜態成員的時候是類的構造函數,裝飾實例成員或者類的原型對象的時候是類的原型對象
參數2:成員的名字,修飾的成員的名字
參數3:參數在函數的參數列表中的索引
參數裝飾器的返回值會被忽略



定義方法getInfo,輸出前綴和要傳入的屬性名的值

再定義一個接口能夠有任意多的屬性,屬性類型能夠是string 能夠是number也能夠是個function(函數)

實例類ClassI,調用繼承過來的getInfo方法,傳入參數1:hihi 參數2:age屬性

在infoType這個屬性前面使用裝飾器,

就會輸出console內容

裝飾器是一個實驗性的功能,在生產環境上儘可能不使用,之後可能會有顛覆性的修改接口

相關文章
相關標籤/搜索