共计 2067 个字符,预计需要花费 6 分钟才能阅读完成。
引言
继上周的文章《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’);
总结
初级程序员的业余生活,学习,学习,学习。