JavaScript 类的基础知识

99 阅读2分钟

1、 类定义

    类声明     class Person {}
    类表达式   const Animal = class {};

2、 类的实例化

1、使用 new 调用类的构造函数会执行如下操作。


(1) 在内存中创建一个新对象。

(2) 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。

(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。

(4) 执行构造函数内部的代码(给新对象添加属性)。

(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

class Person {
  city: string;
  constructor() {
    console.log("xxx");
    this.city = "昆明";
  }
}

2、 类实例化时传入的参数会用作构造函数的参数

class Person {
  city?: string;
  constructor(city?: string) {
    console.log(arguments.length);
    this.city = city;
  }
}

let p1 = new Person("昆明"); // 1
console.log(p1.city);  // 昆明

3、 每个实例都对应一个唯一的成员对象,这意味着所有成员都不会在原型上共享

class Person {
  name: String;
  constructor() {
    this.name = new String("pengze");
  }
}

let p1 = new Person();
let p2 = new Person();
console.log(p1.name); //pengze
console.log(p2.name); //pengze

p1.name = "pp1";
p2.name = "bb2";
console.log(p1.name); //pp1
console.log(p2.name); //bb2

4、添加到this上的所有内容,都会存在不同的实例上, 在类块中定义的所有内容都会定义在类的原型上, 通过static关键字作为前缀 定义在类本身上

class Person {
  name = "Jake";
  constructor() {
    this.name = "pengze";
  }
  setName() {
    console.log(`我在原型上`);
  }
  static getName() {
    console.log(`静态方法存在类的本身上`)
  }
}

let p = new Person();
console.log(p.name); //pengze
console.log(Person.prototype.setName()); //我在原型上
console.log(Person.getName()) // 静态方法存在类的本身上

3、 类的继承

1、ES6 类支持单继承。使用 extends 关键字,就可以继承任何拥有[[Construct]]和原型的对象。很大程度上,这意味着不仅可以继承一个类,也可以继承普通的构造函数

class Vehicle {}

// 继承类

class Bus extends Vehicle {}

let b = new Bus();

console.log(b instanceof Bus); // true

console.log(b instanceof Vehicle); // true

function Person() {}

// 继承普通构造函数

class Engineer extends Person {}

let e = new Engineer();

console.log(e instanceof Engineer); // true

console.log(e instanceof Person); // true

2、 supur的使用

(1.1) 不要在调用 super()之前引用 this,否则会抛出 ReferenceError

(1.2) super 只能在派生类构造函数和静态方法中使用

(1.3) 不能单独引用 super 关键字,要么用它调用构造函数,要么用它引用静态方法

(1.4) 调用 super()会调用父类构造函数,并将返回的实例赋值给 this
 
class Vehicle {
  name: boolean;
  constructor() {
    this.nameBoolean = true;
  }
}
class Bus extends Vehicle {
  constructor() {
    super(); // 相当于 super.constructor()
    console.log(this instanceof Vehicle); // true
    console.log(this); // Bus { nameBoolean: true }
  }
}
new Bus();
(1.5) 如果没有定义类构造函数,在实例化派生类时会调用 super(),而且会传入所有传给派生类的参数。
class Vehicle {
  brand!: string;
  constructor(brand: string) {
    this.brand = brand;
  }
}
class Bus extends Vehicle {}
console.log(new Bus("劳斯莱斯")); // Bus { brand: '劳斯莱斯' }

(1.6) 如果在派生类中显式定义了构造函数,则要么必须在其中调用 super(),要么必须在其中返回一个对象。
class Vehicle {}
class Car extends Vehicle {}
class Bus extends Vehicle {
  constructor() {
    super();
  }
}
class Van extends Vehicle {
  constructor() {
    // super();
    return {};
  }
}
console.log(new Car()); // Car {}
console.log(new Bus()); // Bus {}
console.log(new Van()); // {}