以前在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“,
只不过地址换了,但是名字没有变,所以就是这个道理
使用属性列表来描述类中的属性,什么意思,举个
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);