类的使用
在类中可以添加一个特殊的方法 constructor,我们称该方法为构造函数,构造函数会在我们调用类创建对象的时候执行。
动态赋值
在构造函数constructor中添加属性,为实例属性进行赋值,达到为属性动态赋值的目的。
class Person{
#address = "花果山" // 实例通过#将属性变为私有属性,私有属性只能在类内部才能访问。
#age // 先声明才能访问
constructor(name,age,gender){
// 在构造函数中,this表示当前所创建的对象。
this.name=name
this.#age=age
this.gender=gender
}
// 实例方法
sayHello() {
console.log(this.#name,this.#address)
}
// getter 方法,用来读取属性
get Name() {
return this.#name
}
// setter 方法,用来设置属性
set name(name) {
this.name=name
}
set Age(age) {
if(age >= 0){
this.#age = age
}
}
}
// 在我们调用 Person 的时候相当于调用 constructor
const p1 = new Person("孙悟空",18,'男')
面向对象的特点
封装、继承和多态
-
封装
- 对象就是一个用来存储不同属性的容器。
- 对象不仅负责属性,还要负责数据的安全。
- 直接添加到对象中的属性,并不安全,因为它们可以被任意修改。
- 如何确保数据的安全:
- 私有化属性
- 需要保护的数据设置为私有,只能在类内部使用
- 提供 setter 和 getter 方法来开放对数据的操作
- 属性设置私有,通过getter、setter方法操作属性带来的好处
- 可以控制属性的读写权限,更加灵活
- 可以在方法中对属性的值进行验证:加入if判断
- 属性设置私有,通过getter、setter方法操作属性带来的好处
- 私有化属性
- 封装主要确用来确保数据的安全。
- 实现封装的方式
- 属性私有化:#属性
p1.#address // Uncaught SyntaxError 无法访问到私有属性- 通过getter和setter方法来操作属性
get 属性名() { return this.#属性 }set 属性名(参数) { this.#属性 = 参数 }// 可以添加验证属性
-
继承
- 可以通过 extends 关键字来完成继承
- 当一个类继承另一个类时,就相当于另一个类中的代码复制到了当前类中
- 继承发生时,被继承的类称为父类(超类),继承的类称为子类
- 通过继承可以减少重复代码,并且可以在不修改一个类的前提进行扩展。
- OCP 开闭原则
- 程序应对修改关闭,对扩展开放
class Animal{ constructor(name) { this.name = name } dog.sayhello() { console.log('动物在叫~') } } class Dog extends Animal{ // 在子类中,可以通过创建同名方法来重写父类的方法 sayHello() { console.log('汪汪汪') } } class Cat extends Animal{ // 重写构造函数 contructor(name) { // 重写构造函数时,构造函数的第一行代码必须为 super() super(name) // 调用父类的构造函数 } sayHello() { // 调用一下父类的sayHello super.sayHello() // 在方法中可以使用 super 来引用父类的方法 } } const dog = new Dog("旺财") const cat = new Cat("tom") dog.sayHello(); // 动物在叫~ -
多态
- 在 JS 中不会检查参数类型,所以意味着任何数据都可以作为参数传递。
- 要调用某个函数,无需指定类型,只要对象满足某些条件即可。
- 多态为我们提供了灵活性。