(十一)Class 类

102 阅读3分钟

什么是类

类由属性和方法构成,其中属性表示类的状态,而方法表示类的行为。在类的实例化过程中,会通过构造函数来初始化这些属性。可以通过Class关键字来声明一个类,其也只是个语法糖,本质还是利用原型和原型链的继承来实现

注:函数声明类声明之间的一个重要区别在于,函数声明会提升,类声明不会。

类的构造函数

类自身具有构造函数,其用来初始化对象的状态;类只能通过new关键字调用的。

调用构造函数内部实现过程:

  1. 创建一个新对象,该对象是个空对象。obj = {}
  2. 该对象的__proto__指向类的原型,如Perconobj.__proto__ = Person.prototype
  3. 将该对象赋值给this
  4. 类构造函数指向代码体
  5. 如果类的构造函数没有返回复杂数据类型则返回this,否则返回复杂数据类型
class Person {

  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

const p1 = new Person("p1", 15);
console.log(p1); //{name:'p1',age:15}

关于类的三种方法

类的实例方法

类的实例方法可以通过实例化对象来调用,相当于放到原始构造函数的prototype

class Person {
  constructor(name, age) {
    this.name = name;
    this._age = age;
  }

  // 实例方法
  eating() {
    console.log(this.name + "吃饭");
  }

const p1 = new Person("p", 18);

// 调用实例方法
p1.eating(); //p吃饭

类的访问器属性

类的访问器属性方法同样可以通过实例化对象来调用,也相当于放到原始构造函数的prototype

class Person {

  constructor(name, age) {

    this.name = name;

    this._age = age;

  }


  // 访问器属性 访问器属性允许你在访问属性时执行自定义的读取和写入操作

  get age() {

    console.log("获取age");

    return this._age;

  }

  set age(val) {

    this._age = val;

  }

  

const p1 = new Person("p", 18);

// 访问类访问器

console.log(p1.age); // 获取age 18

类的静态方法

类的静态方法只能通过类来调用,相当于放到原始构造函数的方法中,如:fn.method()

let names = ["p1", "p2", "p3"];

class Person {
  constructor(name, age) {
    this.name = name;
    this._age = age;
  }

  // 3.类方法 只能通过类直接调用,不能通过实例方法调用
  static randomPerson() {
    let nameIndex = Math.floor(Math.random() * names.length);
    let name = names[nameIndex];
    let age = Math.floor(Math.random() * 99);
    return new Person(name, age);
  }

}

const p1 = new Person("p", 18);

// 调用类的静态方法
console.log(Person.randomPerson());

类的继承

基类:父类,派生类:子类

派生类的构造函数

派生类的构造函数和基类的构造函数不同,派生构造函数没有初始的this绑定,而是调用super()方式在构造函数创建一个this绑定,和以下代码的效果类似,其中Person是基类

this = new Person()

super关键字

  1. 不论基类有没有写构造函数,在派生类的构造函数中super()必须在使用thisreturn之前调用。原因就是派生类的构造函数不同。
  2. 基类的静态方法必须也在派生类的静态方法中通过super调用

super关键字可以调用父类的构造方法实例方法静态方法

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  eating() {
    console.log(this.name + "吃饭");
  }

  static personMethod() {
    console.log("逻辑一");
    console.log("逻辑二");
    console.log("逻辑三");
  }

}


class Student extends Person {
  constructor(name, age, sno) {
    // 1.super调用父类构造函数
    super(name, age);
    this.sno = sno;
  }

  studentEating() {
    console.log("学生");
    // 2.super调用父类的实例方法
    super.eating();
  }

  static sonMethod() {
    // 3.super调用父类的静态方法,必须也在静态方法里才能调用父类的静态方法
    console.log("学生");
    super.personMethod();

  }

}

const stu1 = new Student("stu1", 18, "10231");

stu1.eating(); // 学生 stu1吃饭

Student.sonMethod(); // 学生 逻辑一 逻辑二 逻辑三

方法重写

派生类可以重写基类的方法,也就是子类和父类方法名相同,通过子类创建的实例对象调用方法时会调用子类自身的方法,不会调用父类的方法。

class Person {

  constructor(name) {
    this.name = name;
  }

  eating() {
    console.log("人吃饭");
  }

  static running(){
    console.log("人跑步");
  }

}

class Student extends Person {

  constructor(name, sno) {
    super(name);
    this.sno = sno;
  }

  eating(){
    console.log("学生吃饭");
  }

  static running(){
    console.log("学生跑步");
  }
}

const stu = new Student();
stu.eating() //学生吃饭
Student.running() //学生跑步

Class与原始构造函数对比

图片.png

图片.png