typescript中的数据类型
typescript为了使代码编写更加规范,更有利于维护,增加了类型校验,在typescript中主要给我们提供了如下数据类型:
- boolean 布尔型
- number 数值型
- string 字符串型
- array 数组型
- tuple 元组类型
- enum 枚举类型
- any 任意类型
- null
- undefined
- void类型
- never型:是其他类型(null 和 undefined)的子类型,代表从不会出现的值。这代表声明never的变量只能被never类型赋值
函数的写法
- 三点运算符 接受新传过来的值
// 写法一 function sum(...num:number[]):number { for (let i = 0; i < num.length; i++) { sum+=num[i]; } return sum; } sum(1,2,3,4,); // 输出10 // 写法二 function sum(a:number, b:number, ...num:number[]):number { let sum = a +b; for (let i = 0; i < num.length; i++) { sum+=num[i]; } return sum; } sum(1,2,3,4); // 输出10
重载
1.函数重载
- java中方法的重载:指两个或两个以上的同名函数,由于参数不一样,出出现函数重载的情况
- ts中的重载:通过为同一个函数提供多个不同类型的参数,来实现多种功能目的
- ES5中出现同名函数,则写在执行顺序后面的函数会替换之前的函数
2.ts函数重载
- ES5中出现同名函数,则写在执行顺序后面的函数会替换之前的函数 ,但ts则不会
function getResult(str:string):string; function getResult(str:number):number; function getResult(str:any):any { if (typeof str === 'string') { console.log('传参为string型'); } else { console.log('传参为number型') } } getResult('这是string型'); getResult(123); getResult(true); //错误写法,因为在方法重载中没有找到可以匹配boolean型的函数
说明:上面例子中function getResult(str:any):any {}并不是重载的一部分
typescript类说明
-
typescript 定义类时,给我们提供了三种修饰符
- public :公有。 在当前类、子类、外面都可以访问
- protected: 保护。 在当前类、子类可以范围,外面不可以访问
- private : 私有。 在当前类可以范围,子类、外面不可以访问
属性如果不加修饰符,那默认为:public
-
static
不需要实例化,可直接调用
-
多态
定义:父类定义了一个方案,但不去实现,让继承它的子类去实现,每一个子类有不同的表现
-
抽象类
- 抽象类时提供其他类继承的基类,不能直接被实例化
- 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现,并且必须在继承类中实现
- abstract抽象方法只能在抽象类中,否则报错
- 抽象类和抽象方法用来定义标准(供继承类实现的标准)
接口
待更新
命名空间
-
命名空间
- 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的类、函数、接口等放置到命名空间内
- 同java的包、.Net的命名空间一样,Typescropt的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象,命名空间内的对象通过export向外暴露
-
命名空间和模块的区别
- 命名空间:内部模块,主要用于组织代码,避免命名冲突
- 模块:侧重代码服用,一个模块里可能包含多个命名空间
装饰器
修饰器是js过去几年中js最大的成就之一,现已是ES7的标准特性
-
装饰器
装饰器是一种特殊类型的声明,他能被附加到类、方法、属性或参数上,可以修改类的行为。
通俗的讲:装饰器就是一个方法,可以注入到类、方法、属性和参数上来扩展类、方法、属性、参数的功能
-
常见装饰器
-
类装饰器
-
普通装饰器无法传参
-
类装饰器,在类声明之前被声明(紧靠着类声明)
function addClass(params: any) { console.log(params); // params 为当前类 params.prototype.name = '我是重定义的name'; params.prototype.getClass = () => { return this.name; } } @addClass class Animal { public name: string = '我是固有的name'; constractor() { } } let animal = new Animal(); console.log(animal.name); // 输出:我是重定义的name animal.getClass(); // 输出:我是重定义的name
-
-
装饰器工厂
-
带参数的装饰器
// 例子1(重写属性) function addClass(params: any) { console.log(params); // params 为传入的参数 return (target: any) => { console.log(params); // params 为传入的参数 console.log(target); // target 列的原型 target.name = '我是重定义的name'; } } @addClass('我是重定义的name') class Animal { public name: string = '我是固有的name'; constractor() { } } let animal = new Animal(); console.log(animal.name); // 输出:我是重定义的name animal.getClass(); // 输出:我是重定义的name // 例子2(重载方法) function addClass(params: any) { console.log(params); // params 为传入的参数 return class extends Animal { console.log(params); // params 为传入的参数 console.log(target); // target 列的原型 eat() { this.name = '狗'; console.log(this.name + '喜欢吃鱼') } } } @addClass('我是重定义的name') class Animal { public name: string = '猫'; constractor() { } eat() { console.log(this.name + '喜欢吃鱼') } } let animal = new Animal(); console.log(animal.name); // 输出:狗 animal.eat(); // 输出:狗喜欢吃鱼
-
属性装饰器
接收两个参数- 类的原型(静态成员来说是构造函数,对实例成员来说是类的原型)
- 类的属性
function addProperty(params: any) { return function (target:any, attr:any) { console.log(target); // 输出:类的原型 console.log(attr); // 输出:类的属性,本例输出:'name' target[attr] = params; } } class Animal { @addProperty('狗') public name: string = '猫'; constractor() { } eat() { console.log(this.name + '喜欢吃鱼') } } let animal = new Animal(); console.log(animal.name); // 输出:狗 animal.eat(); // 输出:狗喜欢吃鱼
-
方法装饰器
他会被应用到方法的属性描述上,可以用来监听、修改、替换方法定义,接收三个参数:- 类的原型(静态成员来说是构造函数,对实例成员来说是类的原型)
- 方法名称
- 方法的属性的描述
function addMethod(params: any) { return function (target:any, methodName:any, methodDesc) { console.log(target); // 输出:类的原型 console.log(methodName); // 输出:方法名称,本例输出:'eat' console.log(methodDesc); // 输出:方法的属性的描述,本例输出:eat方法的描述 target['name'] = params; // 修改装饰器的方法,如修改传入的参数类型都改为string型 let oldMethod = methodDesc.value; // 保存原class类中的方法 // 修改当前方法 methodDesc.value = function(...arg:any) { console.log(arg); // [111, 'abc'] arg.map((val) => { return String(val); }) console.log(arg); // ['111', 'abc'] // 使用老方法 oldMethod.apply(this, arg); // this:把当前方法传进去,arg把参数传进去。 表示在本方法中调用老方法 } } } class Animal { public name: string = '猫'; constractor() { } @addMethod('狗') eat() { console.log(this.name + '喜欢吃鱼') } } let animal:any = new Animal(); animal.eat(); // 输出:[111, 'abc'] ['111', 'abc'] 狗喜欢吃鱼
-
方法参数装饰器
使用时可以为类的原型添加一些元素数据,接收三个参数:- 类的原型(静态成员来说是构造函数,对实例成员来说是类的原型)
- 方法名称
- 参数在方法参数中的索引
function methodParam(params: any) { return function (target:any, methodName:any, paramIndex:number) { console.log(target); // 输出:类的原型 console.log(methodName); // 输出:方法名称,本例输出:'eat' console.log(paramIndex); // 输出:参数在方法参数中的索引,本例输出:0 target['name'] = params; } } class Animal { public name: string = '猫'; constractor() { } eat(@methodParam('狗') name) { console.log((name || this.name) + '喜欢吃鱼') } } let animal:any = new Animal(); animal.eat(); // 输出:类的原型 eat 0 狗喜欢吃鱼
-
-
装饰器执行顺序
- 属性装饰器 > 方法装饰器 > 方法参数装饰器 > 类装饰器
- 如果有多个同类型装饰器,则先执行后面的
@addClass1 @addClass2 class Animal { @addProperty1() @addProperty2() public name: string | undefined constructor() {} @addMethod1() @addMethod2() eat(@methodParam1() name:string, @methodParams2() color:string) { } } /** * 上例执行顺序为:@addProperty2 > @addProperty1 > @addMethod2 > @addMethod1 > @methodParams2 > @methodParams1 > @addClass2 > @addClass1 * /
-