「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
一、 函数
1. 定义函数:
(1) function关键字定义:
function fun1(x:number, y:number): number {
return x+y;
}
(2)变量形式定义
let fun2:(x:number,y:number) => number;
(3)类型别名定义
type fun3 =(x:number,y:number) => number;
(4)接口定义
interface fun4 {
(x:number,y:number): number;
}
2. 可选参数
写法:参数后加问号。
function fun5(x:number, y?:number):number {
return y ? x+y : x;
}
3. 默认值
参数可设置默认值,当使用默认值,不想传实参时,可写undefined,若是最后一个参数可不写。
function fun6(x:number, y=1, z:number):number {
return x+y+z;
}
console.log(fun6(1,undefined,2));
4. 剩余参数
剩余参数可以使用 ...变量的形式来表示。
function fun7(x:number, ...rest:number[]) {
return x + rest.reduce((pre, cur) => pre+cur);
}
fun7(1,2,3,4)
5.重载
重载:方法名一样,参数不一样,返回类型可以相同也可以不同。
每个重载的方法都必须有一个独一无二的参数类型列表。
function fun8(...rest:number[]):number;
function fun8(...rest:string[]):string;
function fun8(...rest:any[]):any {
let first = rest[0];
if(typeof first == 'string') {
return rest.join('');
}
if(typeof first == 'number') {
return rest.reduce((pre, cur) => pre+cur);
}
}
四、类
1.写法
class 类名 {}
class Animal {
constructor(name:string) {
this.name = name;
}
name: string;
run() {}
}
上例中,
- constructor:构造方法,初始化name方法
- 设置name属性
- 设置run方法
2.继承
写法: 子类型 extends 父类型
super():父类的实例。
class cat extends Animal {
constructor(name: string){
super(name);
}
eat() {
console.log('eat');
}
}
3. 修饰符
(1)public:公有的,类、子类都可见。
class Animal {
public constructor(name:string) {
this.name = name;
}
public name: string;
public run() {}
}
类中的属性和方法默认是public模式,加上public和没加一样,对外部都可见。
(2)private:私有的,当成员被标记成 private时,它就不能在声明它的类的外部访问。
class Animal {
constructor(name:string) {
this.name = name;
}
private name: string;
}
let a1 = new Animal('Amy');
console.log(a1.name); // 报错
以上例子中,name为私有属性,不能在类的实例中访问,只能在Animal类中访问。
(3)protected:受保护的,protected成员在派生类中仍然可以访问。
class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
constructor(name: string) {
super(name)
}
public getElevatorPitch() {
return `my name is ${this.name}`;
}
}
let howard = new Employee("Howard");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误
上例中,Person类中设置了受保护的name属性,Employee类继承Person类,Employee类中能获取到name属性,但Employee实例不能获取name属性。
(4)readonly:只读,只读属性必须在声明时或构造函数里被初始化。
class Animal {
constructor(name:string) {
this.name = name;
}
readonly name: string;
rewriteName() {
this.name = 'qq'; // 报错
}
}
以上例子中rewriteName方法会报错,显示name属性为只读属性,不能修改。
(5)static:设置类的静态属性,这些属性存在于类本身上面而不是类的实例上。
class Animal1 {
static id:string
getId() {
console.log(Animal1.id);
}
}
console.log(Animal1.id);
Animal1类中设置了静态属性id,使用时是用Animal1.id,而不是Animal1实例上的id。
4. 存取器
通过getters/setters来截取对对象成员的访问。get获取成员值,set设置成员值。
class Person1 {
constructor(name: string) {
this.name = name;
}
private name: string;
get myName() {
return this.name;
}
set myName(name: string) {
this.name = name;
}
}
let person1 = new Person1('小红');
console.log(person1.myName); // 小红
person1.myName = '小米';
console.log(person1.myName); // 小米
创建一个person1类,设置存取器getters/setters获取和设置实例属性name的值。
获取值时直接打印person1.myName,设置时直接给person1.myName赋值即可。
5.抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。
不同于接口,抽象类可以包含成员的实现细节。
abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Animal2 {
abstract eat():void;
run():void {
console.log('run');
}
}
class Dog extends Animal2 {
constructor() {
super();
}
eat(){
console.log('dog eat');
}
jump(){
console.log('jump');
}
}
let dog: Animal2; // 允许创建一个对抽象类型的引用
// dog = new Animal2(); //报错:不能创建一个抽象类实例
dog = new Dog(); // 允许对一个抽象子类进行实例化和赋值
dog.eat();
dog.run();
// dog.jump(); // 错误: 方法在声明的抽象类中不存在
上例中,
Animal2作为抽象类不能被实例化,所以new Animal2()时报错;- 但
Animal2可以作为dog变量的类型; Dog作为抽象子类可以被实例化,可以被赋值;dog = new Dog();- 抽象子类必须实现抽象类中的抽象方法。
Animal2中设置了抽象方法eat(),Dog子类中必须实现eat()方法。 - 抽象子类的实例
dog可以获取到抽象类Animal2的非抽象方法run() - 由于抽象子类的实例dog一开始设置的类型为
Animal2,所以不能获取到Dog子类中的jump()方法。