4.5 KiB
Executable File
4.5 KiB
Executable File
面向对象
封装, 继承, 多态
封装: 属性私有化 继承: extends 多态: js不会检查参数的类型,任何数据都可以作为参数传递
es6 class类
替代了es5的构造函数和原型,使之代码结构上更加简洁 简单理解, 类是一个模板, 实例化就是进行个性化填充参数
// 关键字class
class 类名{//类名大驼峰
属性名 = 属性值 //属性直接写, 不能用let
属性名 //也可以不用赋值
函数名() {} //函数写法, 直接写函数名, 不用写function
//ES6的语法, 最终系统会转成es5, 函数是挂载在原型上的, 只占用一份空间
}
class Student {
name = '张三'
age = 33
sayhello(){
console.log('hello')
}
}
let s = new Student()
console.log(s)
console.log(s.name)
s.sayhello()
new的原理
- 开辟内存空间(堆)
- 设置原型链
- 产生this对象
- 初始化: 执行构造函数(这里是执行构造器)
- 返回对象的内存地址
属性
- 非静态属性
- 静态属性: static, 只能通过类访问, 不能通过实例访问
- 私有属性: #, 只能在类内部访问, 数据更安全
- 通过getter方法读取, 通过setter方法修改
class Student {
static name = '张三'
age = 33
#address = '长安'
getAddress(){
return this.#address
}
setAddress(address){
this.#address = address
}
}
let s = new Student()
console.log(s.name, s.age) // undefined 33
console.log(Student.name, Student.age) // 张三 undefined
console.log(s.#address) // must be declared in an enclosing class
console.log(s.getAddress())
console.log(s.setAddress('123'))
如果想读还是正常读, 写需要调用方法
get address(){
return thisl#address
}
setAddress(address){
this.#address = address
}
同理也可以改成直接写
set address(address){
this.#address = address
}
方法
- 非静态方法
- 静态方法: static, 只能通过类访问, 不能通过实例访问
class Student {
static sayhello(){
console.log('hello')
}
saybye (){
console.log('bye')
}
}
let s = new Student()
s.sayhello() // not a function
s.saybye()
Student.sayhello()
Student.saybye() // not a function
constructor 构造器
构造器存在的价值: 初始化属性 只要实例化, 对象就会在产生后的第一件事, 调用constructor
class Student {
constructor(name, age){
console.log('立刻被执行')
console.log(this) // this指向新实例的那个对象
this.name = name
this.age = age
}
sayhello(){
console.log(`hello, my name is ${this.name}`)
}
}
let s = new Student('张三', 18)
s.sayhello()
extends 继承
子类没有的, 直接继承父类, 继承之后, 可以直接使用父类的属性和方法
语法:
1. 定义父类
class 父类{属性和方法}
2. 定义子类要实现继承
class 子类 extends 父类{}
// 如果我还有一个猫的类, 一个鸟的类, 每个类都要创建一遍, 太麻烦, 把公共的抽出来,变成一个公共动物类
class Animal {
name:string
age:number
constructor(name:string, age:number){
this.name = name
this.age = age
}
say(){
console.log('动物在叫')
}
}
class Dog extends Animal {
food: string = "骨头"
say(){
console.log('汪汪汪')
}
}
class Cat extends Animal {
say(){
console.log("喵喵喵")
}
}
const dog = new Dog("小白",1)
const cat = new Cat("小黑",1)
重写
当子类继承了父类后,子类拥有与父类同名的属性或者方法,同名的子类方法或者属性就叫做重写 属性被重写: 被覆盖掉 方法被重写: 不会被覆盖, 在不同的原型中
访问父类被重写的方法/构造函数
super.父类被重写的方法名()
class Father {
name = 'father'
say(){
console.log("I'm father")
}
}
class Son extends Father {
name = 'son'
say(){
super.say() // 调用父类的方法
console.log("I'm son")
}
}
let s = new Son()
s.say()
- 也可以在构造函数中调用父类的构造函数
class Bird extends Animal {
color:string
constructor(name:string, age:number, color:string){
super(name, age)
this.color = color
}
}
重写构造函器
一般写在第一行 构造器可以重写, 必须保证父类的构造器先运行 父类构造器有参数, 就必须给super传入 子类有构造方法且使用this前,必须使用super()
class Bird extends Animal {
color:string
constructor(name:string, age:number, color:string){
super(name, age)
this.color = color
}
}