ts中的class 属性,constructor,方法

1,837 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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)
 }
}