typescript入门(三)函数和类

208 阅读4分钟

「这是我参与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()方法。