TS中类的书写

以前在js中书写类是这样的,然后我们在加上TS的类型检查你会发现报错了

class User {
    constructor(name:string,age:number) {
        this.name=name;
        this.age=age;
    }
}

为什么呢? 在TS中他认为你这样写代码不是很好,因为在TS中你把User这个类写出来以后,

它里面有哪些属性和方法,你应该很清楚的知道,所以TS认为你这些属性应该单独在一个地方写,

而不是使用构造函数constructor动态的创造数据,在js中是可以使用构造函数取动态添加数据,

而在TS中是不允许的,TS认为在创建一个对象后是不允许取给对象添加属性的,

由于动态添加属性,可能会存在一些隐患,所以TS是不允许我们动态添加属性的

const obj = {}
obj.name='蜗牛';
obj.age=18;

知识补充

在TS中这样是不行的,有人可能就会说因为const原因,我只能说小伙子你还年轻,js基础不扎实,

const 我一般是用来定义常量的,就是一些固定的东西比如某个状态码,如 const STATUS=200,

像这样的 放在配置文件中,使用时候导入进行使用,const 说定义的值不能改变,说的其实就是内存地址

基本数据类型内存地址是不会变的,而引用数据类型,内存地址是会改变的,这里为什么还是可以使用const

那是因为const 不能改变的只是引用数据类型的名字,地址是可以换的,比如 const 房间1={},定义一个房间

名字叫”房间1“,虽然我可以给房间里面添加删除东西,但是房间名字没有改变,那我是不是可以吧另外一个房间的名字也改成”房间1“,

只不过地址换了,但是名字没有变,所以就是这个道理


知识点补充完,继续TS,既然TS不允许动态添加属性那该怎么书写呢

使用属性列表来描述类中的属性,什么意思,举个🌰

class User {
    name:string
    age:number
    constructor(name: string, age: number) {
        this.name=name;
        this.age=age;
    }
}
const u= new User("蜗牛",18);
//不能添加属性
u.sex="男"//这里就会报错
//还可以这样赋值
const u= new User();
u.name="蜗牛",18
u.age=18

把属性写在类里面,表示这个类里面有这些属性,在后面使用时只能使用这些属性,不能添加,否则会报错

在这里我想到这个好像有点难受,万一我的属性有很多,那不是要写一堆,感觉好麻烦

属性的初始化检查

有时候我们可能忘记了给对象赋值,如:在构造函数中没有给age赋值

class User {
    name:string
    age:number
    constructor(name: string, age: number) {
        this.name=name;
    }
}
const u= new User("蜗牛",18);

但是他不会报错,但是有些属性我们必须要赋值的,那这个时候怎么办呢

这里我们就得用到一个配置了 strictPropertyInitialization,更加严格的检查属性有没有初始化,会检查属性有没有赋值

{
    "compilerOptions": {
        "target": "es2016",//配置编译目标代码的版本标准
        "module": "commonjs",//配置编译目标使用的模块化标准
        "lib": ["es2016"], //表示默认详情下ts使用的是那一个环境
        "outDir": "./dist",//编译结果的目录
        "strictNullChecks": true,//TS检查变量是否是null
        "removeComments": true,/*编译结果中是否包含注释*/
        "noImplicitUseStrict": true,/*编译结果中是否有"use strict"*/
        "esModuleInterop": true,//启用es模块化交互非es模块导出
        "strictPropertyInitialization": true,//更加严格的检查属性有没有初始化
    },
    "include":["./src"],//执行ts的目录
}

加上这个配置后,上面构造函数中没有给age赋值,TS就会提示age属性报错,我们必须给属性进行赋值

属性默认值

当然我们也可以给属性进行默认值,比如默认性别为”男“,做法有两种

  • 方法1,构造函数参数默认法,这样在创建user对象时可以不传就是默认的男,如果想要修改,则const u= new User("蜗牛",18,"女"),这样就可以了
class User {
      name:string
      age:number
      gender: "男" | "女" 
      constructor(name: string, age: number,gender:"男" | "女" = "男") {
          this.name=name;
          this.age=age;
          this.gender=gender;
      }
  }
  • 方法2,属性默认法,在定义属性时就给默认值,在定义属性gender时,就给默认值为男,这样在构造函数里面就不用给这个属性进行赋值,
    那这里有个问题,既然构造函数里面没有该属性的赋值操作,那该怎么修改该属性呢,如果你想要在const u= new User("蜗牛",18,"女")这里面加一个参数,你会发现没有用,
    因为构造函数都没有该参数,加了也没有,正确的方法时,使用 对象[属性]="XX"; 的方式进行修改,如 u.gender="女";这样就可以改变值了
class User {
    name:string
    age:number
    gender: "男" | "女" = "男"
    constructor(name: string, age: number) {
        this.name=name;
        this.age=age;
    }
}

属性可选值

当属型是可以有值也可以不传时,如当我们的身份证号可以填写也可以不填时,该怎么给属性赋值呢,两种方法

  • 方法1、 “|”符号 IDCard:string | undefined = undefined,这样的写法
class User {
    IDCard: string | undefined =undefined;
    constructor() {
    }
}
  • 方法2、链式操作法 IDCard?: string,像js中的链式操作一样
class User {
    IDCard?: string
    constructor() {
    }
}

只读属性

当某个属性创建后就无法更改时,那这个属性后面就不能在进行修改了,那我们就得用到readonly,加上这个后,在后面就无法进行修改了

class User {
    readonly uid:number
    constructor() {
        this.uid=new Date().getTime()
    }
}
const u= new User();
//这里想修改,结果不让修改,报错
u.uid=1

访问修饰符,可以控制类中的某个成员的访问权限

  • public:默认的访问修饰符,公开的,所有的代码均可访问
  • private: 私有的修饰符,只有在类中可以访问
class User {
    readonly uid:number
    name:string
    age:number
    gender: "男" | "女" ="男"
    IDCard?: string
    private money:number = 1000000//这是自己的钱,不希望外面进行访问,进行修改
    useMoney: number =0//使用钱和赚到的钱
    constructor(name: string, age: number) {
        this.uid=new Date().getTime()
        this.name=name;
        this.age=age;
    }
    makeMoney(){
        this.money +=this.useMoney
        console.log("剩余金额"+this.money)
    }
}

const u= new User("蜗牛",18);
u.useMoney=1000//挣钱
u.makeMoney()//查看还有多少钱

补充:在js中要实现私有的可以使用Symble;当然这些修饰符也可以用在方法上,这样私有方法外部禁止调用

class User {
    private money:number = 1000000//这是自己的钱,不希望外面进行访问,进行修改
    useMoney: number =0//使用钱和赚到的钱
    constructor() {
    }
   private makeMoney(){
        this.money +=this.useMoney
        console.log("剩余金额"+this.money)
    }
}
const u= new User();
u.makeMoney()//这里就会报错,禁止调用该方法

补充

我们这样写,构造函数里面直接赋值给属性,没有做任何操作,这样显得太机械化,麻烦,

class User {
      name:string
      age:number
      constructor(name: string, age: number) {
          this.name=name;
          this.age=age;
      }
  }

TS给了我们一个语法糖, 当一个属性在构造函数里面,没有做任何操作就直接赋值给属性了,可以简写成,如下,这样和上面的写法得到的结果是一样的

这样的写法 有且仅当,属性通过构造函数的参数传递,并且不做任何处理的赋值给该属性,可以进行简写

class User2 {
    constructor(public name: string,public age: number) {}
}
const u2=new User2("可莉",18)
console.log(u2);