目录
装饰器
装饰器(decorator)的主要作用是给一个已有的方法或类扩展一些新的行为,而不是去直接修改它本身。
在ES2015进入Class之后,当我们需要在多个不同的类之间共享或者扩展一些方法或行为的时候,代码会变得错综复杂,极其不优雅,这也就是装饰器被提出的一个很重要的原因。但是ECMAScript的装饰器提案到现在还没有定案,所以来学习一下TypeScript中的装饰器。不过,在TS中,装饰器仍然是一项实验性特性,未来可能有所改变,所以如果要使用装饰器,需要在tsconfig.json的编译配置中开启experimentalDecorators,将它设为true:
"experimentalDacorators":true
装饰器的定义
装饰器是一种特殊类型的声明,它能够被附加到类,方法,访问器,属性或参数上。用@添加
装饰器本质上还是一个函数,在别的语言中已广泛使用,
如: python,但在TS中依旧为一个测试中的版本,若要启用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimental Decorators编译器选项:
-
添加到类上,类装饰器
-
添加到方法上,方法装饰器
-
添加到访问器上,访问器装饰器
-
添加到属性上,属性装饰器
-
添加到参数上,参数装饰器
类装饰器
-
类装饰器就在类声明之前被声明
-
类装饰器被应用于类的构造函数,可以用来观察、修改或替换类定义
-
类装饰器不能用在声明文件中(.d.ts),也不能用在任何外部上下文中(比如declare)
-
类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数
-
如果类装饰器返回一个值,它会使用提供的构造函数替换类的声明
-
类装饰器,不会对类原来的内容进行改变,而是动态的向里面添加内容
export default{}
// 定义装饰器
//先定义一个函数,然后这个函数有一个参数,就是 要装饰的目标,装饰的作用不同,这target代表的东西也不同。定义了这个函数之后,它就可以作为装饰器,使用@函数名的形式,写在要装饰的内容前面。
// 关键字 函数名(结构体 : 属性类型)
function testDecorator(constructor:any){
constructor.prototype.uname="薛之谦"
constructor.prototype.show=()=>{
console.log(`我是帅哥:${constructor.prototype.uname}`);
}
}
@testDecorator
class Person{
}
let p = new Person();
(p as any).show()
函数工厂类装饰器
function testDecorator(flag:boolean){
if(flag){
return function(constructor : any){
constructor.prototype.uname="薛之谦"
constructor.prototype.show=():void =>{
console.log(`我是帅哥:${constructor.prototype.uname}`);
}
}
}else{
return function(constructor : any){
constructor.prototype.show=():void =>{
console.log(`Hello World`);
}
}
}
}
@testDecorator(true)
class Person{
}
let p = new Person();
(p as any).show()
混入Mixins
介绍:除了传统的面向对象继承方式,还流行一种通过可重用组件创建类的方式,就是联合另一个简单类的代码。你可能在Scala等语言里对mixins及其特性已经很熟悉了,但它在JavaScript中也是很流行的。
作用:解决TS中继承—次只能继承一个类的问题
注意点:类的混入不能混入属性名
export default{}
let nameObj = {name:"邓紫棋"}
let ageObj = {age:20}
Object.assign(nameObj,ageObj)
console.log(nameObj);
console.log(ageObj);
模块与命名空间
TS中的模块
Typescript模块的设计理念是可以更换的组织代码。
两个模块之间的关系是通过在文件级别上使用import和export建立的
模块使用模块加载器去导入其它的模块。在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。大家最熟知的JavaScript模块加载器是服务于Node.js的CommonJS和服务于Web应用的Require.js。
模块导出使用关键字export关键字,语法格式如下:
//文件名:modular
export interface modular{
//代码部分
}
要在另外一个文件使用该模块就需要使用import关键字来导入:
import Test = require("./modular")
import Test = require("./modular")
export class UserInfo implements Test.Person{
name="邓紫棋";
age=18
sex="女"
show(){
console.log("你好");
}
}
let p = new UserInfo()
console.log(p);
console.log(p.name);
// import {obj} from "./modular";
// console.log(obj);
TS中的命名空间
项目开发过程中,我们会拔现我们的命名是有严格规范的,我们不能随意的去起名字,但若是都采用尽量标准化的方式去命名,我们又无法避免的会造成污染,TypeScript提供了namespace避免这个问题出现 在TS1.5之前被叫做内部模块,主要用于组织代码,避免命名冲突
-
本质就是定义一个大对象,把变量/方法/类/接口...的都放里面
-
通过export导出
-
通过namespace定义
// namespace A{
// export const a = 100;
// }
// namespace B{
// export const b = 200;
// }
// console.log(A.a);
// console.log(B.b);
// 嵌套命名空间
namespace B{
export const b = 1000
export namespace C{
export const c = 2000
}
}
console.log(B.b);
console.log(B.C.c);
// 简化命名空间
import c =B.C.c
console.log(c);
// 主文件
// 从其他文件引入命名空间
import {D} from "./namespace"
console.log(D.d);
//namespace中代码
export namespace D{
export const d = 10000
}