关于前端:TSclass类和接口

1次阅读

共计 5591 个字符,预计需要花费 14 分钟才能阅读完成。

class能够用来做数据的存储与回显,能将页面的数据分离出来并提取到 class 内,函数也能够抽离到 class,实例化class 进行调用。ts中的 class 类与 jsclass类基本相同,不同点在于 tsclass有数据类型束缚,在应用 class 的时候,必须遵循定义的数据类型束缚,class中有一个 constructor,它能够更改class 的属性值,实例化 class 进行传值的时候,传入的值也必须合乎 constructor 参数的数据类型规定。


class 的应用

class Student {
    // 定义属性
    name : string  = ''
    age : number = 0
    gender : string = ''
    
    // 定义构造函数:为了未来实例化对象的时候,能够间接对属性的值进行初始化
    constructor(name : string,age :number ,gender : string){
        this.name = name
        this.age = age
        this.gender = gender
    }
}

这里的定义属性是实例对象 class 本身的属性,而不是定义在对象原型上的,在实例化 class 的时候能够间接获取到 class 的属性,例如:let student = new Student ,取值:student .name,此时取值必定是一个空,因为这个 name 并没有进行赋值,而是援用了默认值。

赋值操作

let {name,age,gender} = {name : '张三', age : 18, gender : "男"}
let student = new Student(name,age,gender)
console.log(student)  // 打印 name : '张三', age : 18, gender : "男" 

这里 new Student 就是实例化 class, 并将值传入class 进行赋值操作,赋值操作是在 constructor 中实现的,通过 new 关键词实例化对象时,会主动调用 constructor 构造函数,tsconstructor 在接参的时候,须要定义参数的数据类型,这里传入了 name,age,gender,那么在接参的时候,也必须定义这三个值,并且规定的数据类型必须统一。
this.name = name 就是 class 的实例属性 = 传入的 name 参数,这一步就是赋值操作。赋值之后就能够在 let student 这个地位拿到数据。
间接 new class,如果 不传值 或者传一个 null 则会应用 class 内的 默认值 ,相当于是 重置 class的值;如果 new 传入值,那么就以 传入值为准

在应用 calss 时候的注意事项
1、class 的实例属性须要有默认值,如果没有初始化赋值则会报错

class PersonTest0 {
     // 没有默认值 报错
     name : string
 }
 
class PersonTest1 {
    name : string
    constructor(info : any){
        // 此处做了一个判断,并不是间接赋值,也会报错,去掉 if 间接 this.name = info.name 则不会报错
          if(info){this.name = info.name}
    }
}

// 定义了 constructor 然而没有初始化赋值,报错
 class test2 { 
     name : string
 constructor(name : string){// 没有 this.name = name 报错}
 }

2、class能够不必残缺传入定义的属性,传一部分也能够,未传入的以默认值或者 undefined 展现(ts中须要定义传入类型,未传入的用 ? 可选符申明)。

interface IPersonTest {
    name : string
    age : number
    address ?: string
}

class PersonTest {
    name : string = ''
    age : number = 0
    address ?: string = ''
    constructor(info : IPersonTest | null) {if(info){
            this.name = info.name
            this.age = info.age
            this.address = info.address
        }
    }
}

let PInfo = {
    name : 'zs',
    age : 10,
    // address : '湖北'
}
let getPerson = new PersonTest(PInfo)  // 传入 constructor 值,给实例属性赋值
// 打印 zs , 10 , undefined

3、传入的程序并不影响对类的赋值

let PInfo = {
    name : 'zs',
    age : 10,
    address : '湖北'
}
let PInfo2 = {
    name : '东方不败',
    age : 10,
    address : '湖南'
}

let getPerson = new PersonTest(PInfo)  // 传入 constructor 值,给实例属性赋值
console.log(getPerson);
console.log(new PersonTest(null)); // 传入 constructor 值为空则初始化实例属性的值
console.log(new PersonTest(PInfo2));  // 传入的程序并不影响对类的赋值,此处传入的是 PInfo2,失去的就是 PInfo2 的值
console.log(new PersonTest(PInfo));   // 传入的程序并不影响对类的赋值,此处传入的是 PInfo,失去的就是 PInfo 的值


class 内定义方法

class Student {
    name : string 
    age : number
    gender : string

    constructor(name : string ,age :number ,gender : string){
        this.name = name
        this.age = age
        this.gender = gender
    }

    // 定义实例办法
    sayHi(say : string){console.log(`${say}你好, 我叫 ${this.name}, 往年曾经 ${this.age}岁了,我是个 ${this.gender}孩子 `);
    }
}

let {name,age,gender} = {name : '张三', age : 18, gender : "男"}
let student = new Student(name,age,gender)

console.log(student.sayHi('你叫什么名字啊?'));
// 打印 你叫什么名字啊?你好, 我叫张三, 往年曾经 18 岁了,我是个男孩子

此处在 class 外部定义了一个办法,定义方法跟失常写函数是一样的,有参数且能够设置默认参数,参数必须的定义数据类型,class的实例办法取值的话,用 this.xxx 就能够获取到 calss 内的属性值。class的办法间接用 实例对象. 办法名 (student.sayHi()) 即可。
sayHi()这个办法其实是间接定义在 Student.prototype 下面的,因而在类的实例上调用办法,其实是调用原型上的办法


默认值

class的属性和办法都能够有默认值,如果实例化 class 没有传入参数则应用默认值


class cla {name : string = '属性默认值'}
let data = new cla ()   // new cla 间接获取到 name 的值
console.log(data)  // 打印 属性默认值
class cla2 {
    name : string
    constructor(name : string = '东方不败') {this.name = name}
}
let data = new cla2()   // new cla 后 constructor 的 name 赋值给 this.name
console.log(data.name);  // 打印 东方不败
class cla3 {
    name : string
    constructor(name : string = '不败') {this.name = name}
    sayHi(say : string = '西方'){console.log(`${say},${this.name}`);
    }
}
let data = new cla3() // new cla 后, 函数获取 name 的值加上函数本身的默认值
console.log(data.sayHi());  // 打印 西方,不败


静态方法


class openInfo {fun(list) {  // 实例办法
     console.log(list)
  }
    
  static fun2(list) {  // 静态方法
     console.log(list)
  }

}

let list1 = 50
new openInfo().fun(list1)   // 打印 50
// class 的实例属性须要 new , 语法:类名(). 办法名()


let list2 = 100
openInfo.fun2(list2)   // 打印 100
// class 的静态方法不须要 new,语法:类名. 办法()

类相当于实例的原型,所有在类中定义的办法,都不会被实例继承。如果在一个办法的后面加上 static 关键字,就示意该办法不会被实例继承,而是间接通过类来调用,这个就被称为静态方法。

动态属性

通常状况下,类的属性值两种,第一种实例属性,第二种动态属性

第一种: 实例属性 & 实例对象原型

  • 实例属性就是定义在类 constructor 下面,最顶层的地位,不须要this,跟类外部的函数是平级的,这种形式定义的是实例对象本身的属性
  • 而在 constructor 内定义的 this.xxx 则为实例对象的原型属性。class能够不必残缺传入定义的属性,传一部分也能够,未传入的以默认值或者 undefined 展现(ts中须要定义传入类型,未传入的用 ? 可选符申明)。
  • 这两个办法并没有什么实质的区别,实例属性上定义的能够有默认值。

第二种:动态属性 & 静态方法

  • 在实例属性或者实例办法的后面加一个 static,则为动态属性,动态属性不须要new,取值办法:类名. 属性名 即可

    实例属性是须要 new 的,例如 new Person() 或者 new Person(). 办法名() 或者 new Person(). 属性名

动态属性则间接 类名. 属性名,例如:Person. 办法名() 或者 Person. 属性名

class PersonStatic {
    // name 在动态属性中是一个关键字,不容许应用
    //static names : string  // 此处不赋值就是一个 undefined
    static names : string = ''
    static age : number = 0
    static address : string = ''
    static obj : any = {
        user : '南瓜粥',
        money : 5
    }
    static sayHi(){}  // 静态方法
}
console.log(new PersonStatic);  // 打印 PersonStatic 类
console.log(PersonStatic.names,PersonStatic.age,PersonStatic.address); // 获取初始化的值,空则不显示
console.log(PersonStatic.names = '西方求败',PersonStatic.age = 10,PersonStatic.address = '湖北');  // 动态属性改值
console.log(PersonStatic.names = '艺术概论');  // 动态属性改值
console.log(PersonStatic.obj = {user:'紫薯粥',money:6});  // 对象改值
// console.log(PersonStatic = 100);  // 报错

打印后果:

动态属性能够间接改值,改值的程序并不影响它的输入,它与实例属性不同的是,实例属性定义的是实例对象本身的属性, 是在 class 身上的。

constructor能够更改实例属性的值,动态属性 办法 则是间接定义在构造函数 constructor 中的,所以能够间接改值。而且此处也解释了为什么在动态属性中 name 无奈应用,因为 name 被类本身占用了。

  • 不同点
  • class实例属性能够通过构造函数 constructor 传入的值来批量的改值
  • 动态属性必须单条的 类名. 属性名 改值

接口

1、接口能够束缚 class 外部值的数据类型以及办法,class应用接口之后,接口定义的数据类型和办法必须全副真正实现,并且在实现的根底上,class能够有本人的属性和办法。接口内能够定义属性和办法,这里以办法为例子。

// 接口
interface IFly{fly() : string  // 办法 返回字符串类型
}


class Person implements IFly {fly() : string {// 实现接口中的办法,class 没有 fly()会报错
        return '我会飞了'
    }
    
    run() : string {  // calss 本身定义的办法
        return '我会跑了'
    }
}

Person类里必须得有 IFly 定义的 fly(),而且办法得有字符串返回值,否则报错。

2、class类能够实现一个接口也能够实现多个接口,接口中的内容都要真正实现

// IMy 继承下面定义的两个接口
interface IRun{run() : string // 办法 返回字符串类型
}
interface IFly{fly() : string  // 办法 返回字符串类型
}

//  类能够实现一个接口也能够实现多个接口,接口中的内容都要真正实现
class Person2 implements IFly,IRun {fly() : string {return '我会飞了'}
    run() : string {return '我会跑了'}
}

let person2 = new Person2()
console.log(person2.fly(),person2.run());

接口是能够继承的,class能够应用继承的接口,也能够应用多个接口,办法是一样的,对于接口继承,请看另外一篇:【TS】接口和接口继承


案例源码:https://gitee.com/wang_fan_w/ts-seminar

如果感觉这篇文章对你有帮忙,欢送点亮一下 star

正文完
 0