1、命名空间
命名空间:在代码量较大的情况下,为了避免各种变量命名的冲突,可将相似功能的函数、类、接口等放置到命名空间内。同Java的包.Net的命名空间一样,typescript 的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象
命名空间和模块的区别:
命名空间:内部模块,主要用于组织代码,避免命名冲突。
模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间。
namespace A {
interface Animal {
name: string;
eat(): void
}
export class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(`${this.name}汪汪`);
}
}
class Cat implements Animal {
name: string;
constructor(name: string) {
this.name = name
}
eat() {
console.log(`${this.name}喵喵`);
}
}
}
// 想在外部使用命名空间里的方法 需要先暴露 命名空间.调用
let d = new A.Dog('小狗')
d.eat();
/*
也可以将命名空间模块化,引入
export namespace A
*/
2、装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。
通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)
(1)类装饰器:类装饰器是在类声明之前被声明(紧靠着类声明) 。类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。传入一个参数
普通装饰器
function logClass(params: any) {
// params 就是当前类
console.log(params, 'params');
// 动态扩展属性
params.prototype.apiUrl = 'http://'
params.prototype.run = function () {
console.log('我是扩展的方法');
}
}
// 调用装饰器
@logClass
class HttpClient {
constructor() {
}
getData() {
}
}
var http = new HttpClient()
console.log(http.apiUrl);
http.run()
装饰器工厂(可传参)
function logClass(params: string) {
return function (target: any) {
console.log(target, '当前类');
console.log(params, '接收的参数');
target.prototype.apiUrl = params
}
}
@logClass('http://')
class HttpClient {
constructor() {
}
getData() {
}
}
var http = new HttpClient
console.log(http.apiUrl);
类装饰器 重载构造函数
类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明
function logClass(target: any) {
console.log(target, 'target');
// 在装饰器里重载constructor
return class extends target {
apiUrl: any = '我修改了'
getData() {
this.apiUrl = this.apiUrl + '---'
console.log(this.apiUrl);
}
}
}
@logClass
class HttpClient {
public apiUrl: string | undefined
constructor() {
this.apiUrl = '我是构造函数的apiUrl'
}
getData() {
console.log(this.apiUrl);
}
}
var http = new HttpClient()
http.getData()
(2)属性装饰器:属性装饰器表达式会在运行时当作函数被调用,传入2个参数。
1、对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
2、成员的名字
// 属性装饰器
function logProperty(params: any) {
// target 类的原型对象
return function (target: any, attr: any) {
console.log(target, '类的原型对象');
console.log(attr, '属性名');
console.log(params, '属性传入的值');
target[attr] = params
}
}
@logClass('类的传参')
class HttpClient {
@logProperty('http')
public url: any | undefined
constructor() { }
getData() {
console.log(this, 'url');
}
}
var http = new HttpClient()
http.getData()
(3)方法装饰器:它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰会在运行时传入下列3个参数
1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2、成员的名字
3、成员的属性描述符
function get(params: any) {
return function (target: any, methodName: any, desc: any) {
console.log(target, '原型对象');
console.log(methodName, '方法名');
console.log(desc, '描述');
target.apiUrl = 'hahaha'
target.run = function () {
console.log('run');
}
/*
修改装饰器的方法,把装饰器方法里面传入的所有参数改为string类型
1、保存当前方法
*/
var oMethed = desc.value
desc.value = function (...args: any[]) {
args = args.map((value) => {
return String(value)
})
console.log(args, 'args');
// 使用对象冒充修改当前方法,否则会替换原方法
oMethed.apply(this, args)
}
}
}
class HttpClient {
public url: any | undefined
constructor() { }
@get('http://')
getData(...args: any[]) {
console.log(args);
console.log(this.url, '我是getData');
}
}
var http: any = new HttpClient()
console.log(http.apiUrl, 'apiUrl');
http.run()
http.getData(132, '8545')