7、TS中的类

203 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。(百度百科)

ES6中的类写法

举个栗子

class User {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
}

这个写法在 js 最正常不过了, 但是在 ts 这种写法是不正确的。

ts 认为this.name = name; this.age = age 这种动态增加属性是不太合理的, 因为在创建这个 User 时, 应该很清楚User需要的属性应该是提前确定的然后才可以动态增加。

TS中的类写法

需要什么属性应该使用 属性列表 来描述类中的属性。

举个栗子

class User {
    //===== S 属性列表 ===== 
    name: string
    age: number
    //===== E 属性列表 =====
    
    constructor(name, age) {
        this.name = name
        this.age = age
    }
}

注意点: 有时候可能定义了 属性列表 但是忘记书写 构造函数 部分

class User {
    //===== S 属性列表 ===== 
    name: string
    age: number
    //===== E 属性列表 =====
}

这里的 Username、age 的默认值为 undefined, 但是我明确的告诉它为 string、number所以我希望 ts 在这种情况下提示我写法错误, 可以在 tsconfig.json 添加配置:compilerOptions.strictPropertyInitialization : true 使用更加严格的方式来检查属性的初始化。 加上配置后, ts 就会提示 User 忘记了属性的初始化。

属性初始化

属性的初始化可以在 constructor 中完成, 也可以在 属性列表 中完成。

假如 User 有一个 sex 属性的默认为 男, 就可以这样写

class User {
    //===== S 属性列表 ===== 
    name: string
    age: number
    sex: '男' | '女' = '男'
    //===== E 属性列表 =====
    
    constructor(name, age) {
        this.name = name
        this.age = age
    }
}

当在 属性列表 列表中初始化之后, 就可以不用在 constructor 初始化了, 当然也可以在 constructor 初始化

class User {
    //===== S 属性列表 ===== 
    name: string
    age: number
    sex: '男' | '女'
    //===== E 属性列表 =====
    
    constructor(name, age, sex:'男' | '女' = '男') {
        this.name = name
        this.age = age
    }
}

使用 js 的参数默认值也能搞定。

访问器(ES6中的语法)

控制属性的读取和赋值

开发中有一种场景, 就是对用户的年龄赋值, 但是对年龄有几种要求, 不能是负数、小数、大于200, 那么就需要对 年龄属性进行精密的控制, 这是就能使用到访问器。

我们可能会这样书写代码

class User {
    constructor(public name: string, private _age: number = 18) {
        this.name = name
        this._age = _age
    }

    //获取年龄
    getAge(): number {
        return Math.ceil(this._age)
    }

    //设置年龄
    setAge(value: number): void {
        //在这里可以对val做一些处理
        if (value < 0) {
            this._age = 0
        } else if (value >= 200) {
            this._age = 200
        } else {
            this._age = value
        }
    }
}

const u: User = new User('zhangsan')

u.setAge(20)

u.getAge() //20

通过函数的方式来控制内部的私有属性

这种写法完全没有问题, 但是在使用的时候感觉上获取年龄是调用一个函数, 可能会觉得有点别扭, 为了达到使用上直接给属性赋值的写法就可以使用 访问器 改造一下。

class User {
    constructor(public name: string, private _age: number = 18) {
        this.name = name
        this._age = _age
    }

    //获取年龄
    get age(): number {
        return Math.ceil(this._age)
    }

    //设置年龄
    set age(value: number) {
        //在这里可以对val做一些处理
        if (value < 0) {
            this._age = 0
        } else if (value >= 200) {
            this._age = 200
        } else {
            this._age = value
        }
    }
}

const u: User = new User('zhangsan')

u.age = 20 //在赋值感觉上 是给一个属性赋值

u.age //20

体现在使用上的方便快捷

还可以把上面的 set 函数删除, 这样 age 就是一个可读的属性了(本质是执行函数)。

总结

TS 中的类更像后端语言的写法, 搭配上访问修饰符,让类的书写更加有条理。