开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
什么是class?
在我的理解,class是创建对象实例的模板,通过new关键字我们可以创建具备预设属性和方法的对象。ts全面支持es6描述的class关键字。
如何创建一个class?
class ClassName {
propertyA
propertyB
}
类属性
上面代码创建了一个名为ClassName的class,并具备两个属性propertyA和propertyB,该属性默认是"公共的",“可写的”。由于没有指定属性的类型,所以会被默认赋值为"any"。我们可以显示地为属性赋予类型,如
class ClassName {
propertyA: string | undefined
propertyB: number | undefined
}
strictPropertyInitialization
上面代码指定属性类型为undefined是因为开启了ts "strictPropertyInitialization"规则,此规则指定类属性应该被初始化并且此规则不应该被取消。如果因为某些原因你想要通过其他方式来初始化类属性,可以使用上述方式或者断言!来避免报错。如
class ClassName {
propertyA!: string
propertyB!: number
}
我们可以在创建类属性的时候同时给属性默认值,这样的话ts会自动推断属性的类型,并且在实例化类的时候给属性赋值。如
class ClassName {
propertyA = "initial value"
propertyB = 0
}
const cNI = new ClassName();
console.log(cNI.propertyA) // initial value
console.log(cNI.propertyB) // 0
cNI.propertyB = 'string value' //Type 'string' is not assignable to type 'number'
readonly
此关键字可以放在类属性前,作用是避免在构造函数外给类属性赋值,如
class ClassName {
readonly propertyA: string = 'abc'
someotherMethod(){
this.propertyA = "efg" // Cannot assign to 'propertyA' because it is a read-only property
}
}
constructor函数
constructor函数是一个特殊的函数,当我们实例化类的时候会调用该函数,允许我们传参并且覆盖类属性的默认值等。如
class ClassConstructor {
propertyA
constructor(propertyAVal:number){
this.propertyA = propertyAVal;
}
}
const cc = new ClassConstructor(1)
与普通函数不同的是,constructor函数不允许创建泛型(类型变量)或返回非该实例类型,如
class ClassConstructor {
readonly propertyA: string = 'abc'
constructor<Type>(arg:Type):Type{ //Type parameters cannot appear on a constructor declaration
return '' // Return type of constructor signature must be assignable to the instance type of the class
}
}
constructor函数支持重载,如
class ClassConstructor {
propertyA;
propertyB;
constructor(oneParam: number);
constructor(oneParam: number,twoParam: string);
constructor(oneParam:number,twoParam?: string){
this.propertyA = oneParam;
if(twoParam){
this.propertyB = twoParam
}
}
}
const cc = new ClassConstructor(1,'2')
更多关于ts中重载的知识可以看我的另一篇文章:ts中的重载
类属性初始化检测与constructor关系
ts会检测类属性在constructor上的初始化,如
class ClassNameP {
propertyA:string
constructor(){
this.propertyA = 'initial value'
}
}
但其不会检测在constructor上调用方法对类属性的初始化,因为在constructor上调用的方法有可能被子类覆盖而导致类属性没初始化,如
class ClassName {
propertyA:string //Property 'propertyA' has no initializer and is not definitely assigned in the constructor
propertyB = 0
constructor(){
this.initpropertyA()
}
initpropertyA(){
this.propertyA = "str"
}
}
class ClassNameC extends ClassName{
initpropertyA(){
console.log('I do nothing')
}
}
const cNI = new ClassNameC();
console.log(cNI.propertyA) // undefined
//假如将 ClassNameC中的initpropertyA方法去掉,则console.log(cNI.propertyA) 会返回str
super函数
当子类拥有构造函数时,需要在子类的顶部调用super函数
class Base {
}
class Child extends Base {
p: string;
constructor(){
//Constructors for derived classes must contain a 'super' call
}
}
Child应修改为
class Child extends Base {
p: string;
constructor(){
super()
this.p = 'str'
}
}
类方法
在类中创建方法以及方法的作用和书写普通方法一致,只是不用书写function关键字,并且在方法中访问类属性需要使用this关键字
class ClassName {
someP = 'str'
someMethod():void{
console.log("This is a class method")
console.log(this.someP)
}
}