TypeScript中的函数和类你了解吗

目录

  • 函数
    • 作为参数
    • 定义函数
    • 函数参数的类型
    • 可选类型
    • 参数默认值
    • 剩余参数
    • this的默认推导
    • 函数重载
    • 初始化
    • 继承
    • 多态
    • 成员修饰符
  • 总结

    函数 以下声明了一个函数类型,通过type来定义类型别名,void 表示没有返回值
    type fnType = () => void;


    作为参数
    函数可以作为参数,传递到另一个函数中
    type fnType = () => void; function foo(fn: fnType) {fn(); }function bar() {console.log("bar"); }foo(bar); // bar

    与js代码不同的点在于传入的参数需要定义类型注解

    定义函数
    定义函数的时候,需要给入参指定类型注解,返回值如果可以自行推导出来,也可以不写,如 add 和 minus 函数,但是作为参数时,是必须要写的,如 calc 函数中的入参 fn
    function add(num1: number, num2: number): number {return num1 + num2; }function minus(num1: number, num2: number): number {return num1 - num2; }function calc(num1: number,num2: number,fn: (num1: number, num2: number) => void) {console.log(fn(num1, num2)); }calc(30, 20, add); // 50calc(30, 20, minus); // 10


    函数参数的类型
    ts中函数会规定参数的类型和个数,当个数不确定时,可以使用可选类型、剩余参数、默认值

    可选类型
    可选类型相当于该定义的类型和undefined的联合类型,所以参数有三种选择、传入该类型、不传或者undefined
    function foo(x: number, y?: number) {console.log(x, y); }foo(1, 2); // 1 2foo(3); // 3 undefinedfoo(4, undefined); // 4 undefined


    参数默认值
    参数设置了默认值就使之称为了可选类型,不过有默认值的参数最好放在必传参数后面
    function baz(x: number = 20, y: number) {console.log(x, y); }baz(10, 20); // 10 20baz(undefined, 20); // 20 20


    剩余参数
    剩余参数要放在必传参数之后
    function sum(num: number, ...args: number[]) {console.log(num, args); }sum(10); // 10 []sum(10, 20); // 10 [20]sum(10, 20, 30); // 10 [20, 30]


    this的默认推导
    在对象的方法中定义的this,ts是可以自动推导的,但是独立函数中的this,是推导不出来的。
    TypeScript中的函数和类你了解吗
    文章图片

    必须要在独立函数中定义this的类型
    type ThisType = { name: string }; const eating = function (this: ThisType) {console.log(this.name + " eating~"); }; const person = {name: "kiki",eating,}; person.eating()


    函数重载
    函数重载指的是函数名相同,参数个数或者类型不同,所定义的多个处理方法。
    比如需要对字符串拼接或者数字求和操作,虽然我们知道 + 号可以用在字符串和数字上,但是在类型检测严格的ts代码中,这样写编译是不通过的,需要使用【类型缩小】,缩小类型的判断,再进行处理。
    TypeScript中的函数和类你了解吗
    文章图片

    通过联合类型,参数组合的可能性越多,需要越多的if语句来进行判断,并且函数的返回值类型也是未知的,在这种情况下可以使用【函数重载】
    在ts中,定义函数名和参数类型的重载函数,再通过实现函数来定义具体实现。 会根据数据类型在重载函数中调用,再执行实现函数的代码。
    function add(x: number, y: number): number; function add(x: string, y: string): string; function add(x: any, y: any) {return x + y; }console.log(add(1, 2)); console.log(add("a", "b"));

    如果传递的参数与重载函数中定义参数不同,是无法通过编译的。
    TypeScript中的函数和类你了解吗
    文章图片



    初始化
    类中定义的变量需要初始化,可以在定义类的时候就赋值或者通过constructor来操作
    class Person {name: string; age: number; constructor(name: string, age: number) {this.name = name; this.age = age; }}const person = new Person("alice", 20);


    继承
    ts和js中一致,都是通过 extends 实现继承,使用父级参数和方法时使用 super 关键字。
    class Person {name: string; age: number; constructor(name: string, age: number) {this.name = name; this.age = age; }}class Student extends Person {sno: number; constructor(name: string, age: number, sno: number) {super(name, age); this.sno = sno; }}const student = new Student("alice", 20, 1);


    多态
    使用多态可以写出更加具备通用性的代码,如果想要实现多态首先得有继承,并且父类引用指向子类对象。
    class Animal {action() {console.log("animal action"); }}class Dog extends Animal {action() {console.log("dog running"); }}class Fish extends Animal {action() {console.log("fish swimming"); }}function doAction(animals: Animal[]) {animals.forEach((animal) => {animal.action(); }); }doAction([new Dog()]); doAction([new Dog(), new Fish()]); doAction([new Dog(), new Fish(), new Animal()]);

    这里相当于 const animal1: Animal = new Dog() ,看起来是 Animal 对象,其实是 Dog 对象,这里的父类引用指向的是子类对象,所以最后执行的是 Dog 对象的方法
    TypeScript中的函数和类你了解吗
    文章图片


    成员修饰符
    成员修饰符有以下三种
    • public 表示共有的,任何地方都可见,当没有定义成员修饰符时,默认为public
    • private 私有的,只有类中能够访问到
    • protected 被保护的,表示类自身和子类可以访问到
    public
    class Person {public username: string = "alice"; getName() {return this.username; }}const person = new Person(); console.log(person.username);

    【TypeScript中的函数和类你了解吗】private
    通过private修饰的变量,在实例对象上也是不可访问的。
    TypeScript中的函数和类你了解吗
    文章图片

    protected
    通过protected修饰的变量,在实例对象上也是不可访问的。
    TypeScript中的函数和类你了解吗
    文章图片

    readonly
    readonly表示该属性只读,初始化了之后就不能以任何方式修改,无论是在类内部,还是修改实例对象,但当它是一个对象时,只要不改变它的内存地址,修改对象的属性是可以的。
    TypeScript中的函数和类你了解吗
    文章图片

    访问器
    访问器给私有属性提供get/set方法,让我们在类外部获取/修改私有属性
    class Person {private _name: string; constructor(newName: string) {this._name = newName; }get name() {return this._name; }set name(newName) {if (newName) this._name = newName; }}const person = new Person("alice"); console.log(person.name); person.name = "kiki"; console.log(person.name); person.name = ""; console.log(person.name);

    通过get/set属性来修改私有属性可以做到拦截/判断的作用
    TypeScript中的函数和类你了解吗
    文章图片

    静态成员
    静态成员通过 static 关键字来定义,通过 static 定义的属性,是定义在类自身的,只能通过自己访问,在类内部和实例对象都是无法访问到的。
    TypeScript中的函数和类你了解吗
    文章图片

    抽象类
    在定义很多通用的调用接口时,我们通常会让调用者传入父类,通过多态来实现更加灵活的调用方式。
    但是,父类本身可能并不需要对某些方法进行具体的实现,所以父类中定义的方法, 我们可以定义为抽象方法。
    abstract class Shape {abstract getArea(): void; }class Circle extends Shape {private radius: number; constructor(radius: number) {super(); this.radius = radius; }getArea() {return this.radius * this.radius * 3.14; }}class Rectangle extends Shape {private width: number; private height: number; constructor(width: number, height: number) {super(); this.width = width; this.height = height; }getArea() {return this.width * this.height; }}function calcArea(shape: Shape) {return shape.getArea(); }console.log(calcArea(new Circle(3))); console.log(calcArea(new Rectangle(2, 6)));

    抽象方法和方法通过 abstract 来修饰,并且抽象类定义时有两条规则:
    • 抽象方法必须要在子类实现
    • 抽象类是不能被实例化的
    TypeScript中的函数和类你了解吗
    文章图片

    类的类型
    类本身也是可以作为一种数据类型的,可以用作类型注解。
    class Person {name: string = "alice"; eating() {}}const person: Person = {name: "kiki",eating() {console.log("i am eating"); },}; function printPerson(person: Person) {console.log(person.name); }printPerson(new Person()); printPerson(person); printPerson({ name: "macsu", eating() {} });

    只要符合类的格式,就可以使用类的类型
    函数和类在JS和TS中都是至关重要的,可以帮助开发者更好规范开发时的代码,减少线上故障~

    总结 以上就是关于TypeScript函数和类的内容,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

      推荐阅读