把现实中的物体抽象到程序里面,就是以对象(Object)的形式存在的。
对象数据被称为属性。
对象的功能被称为方法。
类 class
人类,狗类…,一系列相似物体的集合,相同的类具有相同的属性和方法
定义
class cat {
name: string;
age: number;
static maxAge: number = 10; // 静态属性,就是这个类统一的属性
run() {
console.log("running")
}
eat() {
console.log("eatting")
}
}
实例 new xxx( )
就是类的一个实例,可以想象成猫类其中有一只叫做Tom,毛是灰色的,Tom是cat类的一个实例。
let Tom = new cat() // 创建实例
属性、方法
公共属性(public 或 省略):普通的属性都是公共属性,任意访问和修改
只读属性(readonly):只能读取,不能修改值
静态属性(static):这个类统一的属性,可以直接访问这个类的静态属性,而不是通过实例
私有属性(private):实例无法直接获取或修改的属性,只能通过这个类的某些方法来获取或修改。
好处是主动权在这个类,我不想让你获取不想让你改,你就没法搞。
或者你获取、修改时可以进行判断,符合我想要的规则,才让你搞。
子类继承后也无法直接操作私属性。
保护属性(protected):受保护的属性,只能在自己类或者子类中访问和修改,无法通过实例访问修改
class cat {
// 定义的是实例属性,需要通过创建实例并赋予初始值才能访问
name: string;
readonly leg: number = 4;// 只读属性,只能读取,不能修改值
// 静态属性,就是这个类统一的属性,可以直接访问这个类的静态属性
static maxAge: number = 10;
// 私有属性,只有这个类有,实例无法去修改,只能通过类的方法去访问
private _life:number = 9
// 构造函数,见下
constructor(n:string){
this.name = n
}
// 定义实例的方法,需要通过创建实例就可以直接调用执行函数
run() {
console.log("running")
}
// 静态方法,就是这个类统一的属性,可以直接调用这个类的静态方法
static eat() {
console.log("eatting")
}
// 一般通过方法获取私有属性的值
showLife(){
return `猫有${this._life}条命`
}
// 或者通过 get方法 获取私有属性的值
get life(){
return this._life
}
// 一般通过方法修改私有属性的值
die(n:number){
this._life -= n; // 只能通过自己的方法,修改私有属性
console.log(`还剩下${this._life}条命`);
}
// 或者通过 set方法 修改私有属性的值
set life(n:number){
if (n>0) {
this._life = n
}
}
}
const Tom = new cat("Tom")
console.log(Tom.name)
console.log(cat.maxAge) // 可以直接访问这个类的静态属性
console.log(Tom.showLife()) // 无法直接访问私有属性,必须通过内部的方法
console.log(Tom.life) // 无法直接访问私有属性,除非get方法定义后才能访问
console.log(Tom.die(2)) // 无法直接修改私有属性,必须通过内部的方法
console.log(Tom.life = 8) // 无法直接修改私有属性,除非set方法定义后才能修改
Tom.run()
cat.eat() // 可以调用访问这个类的静态方法
构造函数(构造方法) constructor
创建实例时,告诉程序怎么给实例赋予初始值
class cat {
name: string ;
age: number ;
static maxAge: number = 10;
// 定义构造器,用于帮助创建实例时,赋予初始值
// 每创建一个实例,都会调用一次构造函数
constructor(n:string,a:number){
console.log(this); // this 指的是当前新创建的实例
this.name = n; // 传参数进来赋初始值
this.age = a;
}
run() {
console.log(this.name + " is running") // this 指的是当前新创建的实例
}
static eat() {
console.log("eatting")
}
}
const Tom = new cat("Tom",4)
console.log(Tom);
Tom.run(); // Tom is running
简写
!可能为空
ts会判断你将要赋值的有没有可能为空,严格的验证可能会报错,如果你确定不会为空,可以加一个!号在后面,告诉ts我确定这个不会为空
继承 extends
可以继承某个类的所有属性和方法,方便减少代码量
/**
* 动物类
* 定义一个动物类
*/
class animal {
name: string ;
age: number ;
constructor(n:string,a:number){
console.log(this); // this 指的是当前新创建的实例
this.name = n; // 传参数进来赋初始值
this.age = a;
}
run() {
console.log(this.name + " is running")
}
say() {
console.log("动物在叫")
}
}
/**
* 猫类
* 定义一个猫类,继承动物类,猫也算动物,可以有名字、年龄等动物的属性,和跑步、叫喊等动物的方法
*/
class cat extends animal { // 继承
// 也可以额外定义猫类自己的属性
leg:number = 4;
color:string;
// 子类的构造函数要注意,需要调用父类的构造函数,传父类需要的参数
constructor(n:string,a:number, l:number,c:string){
super(n,a); // 这里调用父类构造函数,把子类创建实例时的参数传入
this.leg = l;
this.color = c;
}
eat() {
console.log("eatting")
}
run() {
super.run() // super 表示父类,这里调用父类的方法
}
say(){ // 重写父类的方法
console.log("喵")
}
}
const Tom = new cat("Tom",4,4,"black")
Tom.say(); // 喵
抽象类 abstract
接口 interface
可以当做声明一个类型使用,对类进行限制,而且可以重复定义(自定义类型不可以重复定义),重复的结果是叠加。
属性不允许有实际值,方法都是抽象方法(没有实体),只考虑结构
接口就是定义一个规范,就像水管的接口,必须满足一定的规范,才能连接起来。
实现接口 implements,就是怎么满足规范。
抽象类和接口的区别
1、抽象类,可以有普通属性普通方法,也可以有抽象方法
接口,全都是没有属性,抽象方法
2、抽象类用继承 extends
接口用实现 implements
泛型
用法
1、前期不确定类型,使用时再确定,此时搞个变量,用变量表示类型
2、限定函数的参数必须具有某些属性
类分模块
每个类放在单独文件里,然后用es6的 export 暴露这个类,其他页面需要时 import 导入这个类
====================
HTML接口
HTML元素
感叹号!是告诉ts,我们确定这个不为空,否则会提示有可能为空