引言
繼上週的文章《TypeScript
註解(上)》,補充在最後未實現的屬性註解。
本文可能需要紮實的JavaScript
功底,我儘量給大家通俗地講解。
實現
建立新項目
上週的項目建立的太不正規了,直接建個文件夾,然後寫的TS
代碼,太過不規範。
這次我們使用npm init
初始化一個新的前臺項目。
創建成功後,項目中就出現了我們熟知的package.json
文件。
安裝依賴
本次,我們需要使用反射實現一些高級的功能。
反射是指計算機程序在運行時可以訪問、檢測和修改它本身狀態或行爲的一種能力。
根據官方文檔的環境要求,使用TypeScript
反射,我們需要先安裝reflect-metadata
包。
npm i reflect-metadata --save
屬性註解
屬性註解在屬性上聲明,屬性註解的表達式在運行期間像函數一樣被調用,並帶着以下兩個參數:
- 如果是在靜態成員上,則是類的構造函數;如是在實例成員上,則是類的原型。
- 成員的名稱。
所以,一個標準的屬性註解如下所示:返回一個帶有兩個參數的閉包。
function annotation(target: string) {
return function(target, propertyKey) {
}
}
看下面的實例代碼:這裏直接返回Reflect.metadata
代替原閉包,因爲metadata
方法的返回值,就符合該規範。
import "reflect-metadata";
// 聲明唯一的元數據key
const formatMetaDataKey = Symbol("format");
// 前綴註解
function prefix(target: string) {
// 根據key將前綴存至元數據中
return Reflect.metadata(formatMetaDataKey, target);
}
class Person {
constructor(message: string) {
this.message = message;
}
@prefix("hello, ")
message: string;
speak(): void {
// 獲取元數據前綴,key,當前對象,message屬性
const prefix = Reflect.getMetadata(formatMetaDataKey, this, "message");
console.log(prefix + this.message);
}
}
const person = new Person("world");
person.speak();
通過在字符串屬性上聲明的prefix
註解,來添加該字符串應該顯示的前綴。
功能很簡單,也就不再贅述了。以後想寫類似功能時照葫蘆畫瓢就是了,這裏主要是對一些比較繁瑣的代碼加以研究。
Symbol
大家想必注意到了這裏的Symbol
了,這是個什麼東西呢?
// 聲明唯一的元數據key
const formatMetaDataKey = Symbol("format");
Symbol
是一種新的基本數據類型。
去Google
搜索JavaScript
數據類型,發現谷歌的第一條已然過時,面試也常考,這裏糾正一下。
JavaScript
共有7
種數據類型,重點!!!
6
種基本數據類型:
Boolean
Null
Undefined
Number
String
-
Symbol
(ECMAScript 6
新定義)
和Object
。
例子
說來說去,Symbol
到底是個啥玩意?一個例子帶你看明白。
let obj = {
id: 1
};
obj['id'] = 2;
// 覆蓋了原id
console.log(obj);
const id = Symbol('id');
obj[id] = 3;
// 添加Symbol key的屬性
console.log(obj);
const id2 = Symbol('id');
obj[id2] = 6;
// 不覆蓋原Symbol key
console.log(obj);
對象中允許字符串或Symbol
作爲key
,從這個例子我們可以看出,字符串的key
不具有唯一性,而Symbol
的key
能保證唯一,不進行覆蓋。
Token
這個唯一性覆蓋問題就像之前在網上送檢項目中遇到的問題,因爲項目已停工,也就沒有和大家提。這裏和大家簡單說一下。
使用的全局配置是使用字符串注入的,因爲是一個容器,假設我們的框架中也用到了'CONFIG'
的字符串注入,那我們加入的配置就會覆蓋原框架配置,給框架注入了錯誤的對象,然後就出現了錯誤但是就是找不着原因的一系列問題。
providers: [
{ provide: 'CONFIG', useValue: YUNZHI_GLOBAL_CONFIG }
]
class TestComponent {
constructor(@Inject('CONFIG') private config) {
}
}
其實Angular
已經解決,以後不要再通過字符串注入,推薦通過InjectionToken
注入。
const CONFIG_TOKEN = new InjectionToken<VALUE_TYPE>('CONFIG');
總結
初級程序員的業餘生活,學習,學習,學習。