返回

搞定静态属性和方法,轻松理解 JavaScript 类的本质

前端

静态属性和方法:超越实例的共享数据和行为

在 JavaScript 中,静态属性和方法允许你创建属于类本身而不是其实例的数据和行为。这使得你可以存储和操纵整个类共享的信息,并定义在类级别执行的操作。

静态属性

超越实例的共享数据

静态属性属于类本身,而不是类的实例。无论创建多少个类的实例,它们都共享相同的静态属性。这意味着你可以存储对于整个类而言是公共的数据或配置,而无需为每个实例创建单独的副本。

代码示例:

class Car {
  static numWheels = 4;

  constructor(make, model) {
    this.make = make;
    this.model = model;
  }
}

const car1 = new Car("Tesla", "Model S");
const car2 = new Car("Toyota", "Camry");

console.log(Car.numWheels); // 4
console.log(car1.numWheels); // undefined

在这个例子中,numWheels 是一个静态属性,它存储了汽车类的所有实例共享的车轮数量。

静态方法

超越实例的共享行为

静态方法也属于类本身,而不是类的实例。静态方法可以访问静态属性,但不能访问实例属性。静态方法通常用于执行与类本身相关但与特定实例无关的操作。

代码示例:

class Car {
  static numWheels = 4;

  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  static getCarInfo() {
    return `This car has ${this.numWheels} wheels.`;
  }
}

const car1 = new Car("Tesla", "Model S");
const car2 = new Car("Toyota", "Camry");

Car.getCarInfo(); // "This car has 4 wheels."
car1.drive(); // "The Tesla Model S is driving."

在这个例子中,getCarInfo 是一个静态方法,它返回有关汽车类的所有实例共享的车轮数量的信息。

访问控制

把控数据和行为的可见性

JavaScript 中的访问控制决定了属性和方法的可见性。静态属性和静态方法默认都是公开的,这意味着它们可以在任何地方访问。然而,你也可以使用访问控制修饰符来限制它们的可见性。

代码示例:

class Car {
  #numWheels = 4; // 私有静态属性

  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  static #getCarInfo() { // 私有静态方法
    return `This car has ${this.#numWheels} wheels.`;
  }

  drive() {
    console.log(`The ${this.make} ${this.model} is driving.`);
  }
}

const car1 = new Car("Tesla", "Model S");
const car2 = new Car("Toyota", "Camry");

console.log(Car.#numWheels); // 报错:私有属性无法访问
console.log(Car.#getCarInfo()); // 报错:私有方法无法访问
car1.drive(); // "The Tesla Model S is driving."

在这个例子中,#numWheels#getCarInfo 是私有的,这意味着它们只能在 Car 类内部访问。

封装

隐藏实现细节,彰显代码简洁性

封装是将数据和行为捆绑在一起,并隐藏实现细节的一种技术。静态属性和静态方法可以帮助你实现封装,让代码更加简洁和易于维护。

代码示例:

class Car {
  #numWheels = 4;

  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  static getCarInfo() {
    return `This car has ${this.#numWheels} wheels.`;
  }

  drive() {
    console.log(`The ${this.make} ${this.model} is driving.`);
  }
}

const car1 = new Car("Tesla", "Model S");
const car2 = new Car("Toyota", "Camry");

console.log(Car.getCarInfo()); // "This car has 4 wheels."
car1.drive(); // "The Tesla Model S is driving."

在这个例子中,#numWheels 属性和 #getCarInfo 方法隐藏在 Car 类内部,只暴露了必要的接口(如 getCarInfo 静态方法和 drive 实例方法)。这使得代码更加简洁和易于维护。

多态

面向对象编程的核心奥义

多态是指在父类和子类的层次结构中,子类可以重写父类的方法,并提供不同的实现。静态属性和静态方法也可以支持多态,子类可以继承父类的静态属性和静态方法,并根据需要进行修改。

代码示例:

class Car {
  static numWheels = 4;

  static getCarInfo() {
    return `This car has ${this.numWheels} wheels.`;
  }

  drive() {
    console.log(`The ${this.make} ${this.model} is driving.`);
  }
}

class ElectricCar extends Car {
  static numWheels = 4; // 子类继承父类静态属性

  static getCarInfo() { // 子类重写父类静态方法
    return `This electric car has ${this.numWheels} wheels and zero emissions.`;
  }

  drive() { // 子类重写父类实例方法
    console.log(`The ${this.make} ${this.model} is driving silently.`);
  }
}

const car1 = new Car("Tesla", "Model S");
const electricCar1 = new ElectricCar("Tesla", "Model X");

console.log(Car.getCarInfo()); // "This car has 4 wheels."
console.log(ElectricCar.getCarInfo()); // "This electric car has 4 wheels and zero emissions."
car1.drive(); // "The Tesla Model S is driving."
electricCar1.drive(); // "The Tesla Model X is driving silently."

在这个例子中,ElectricCar 子类继承了 Car 父类的静态属性和静态方法,并重写了 getCarInfo 静态方法和 drive 实例方法以提供不同的实现。

代码复用

共享代码,提升开发效率

静态属性和静态方法可以帮助你实现代码复用。你可以在父类中定义静态属性和静态方法,然后在子类中继承它们。这样,子类就可以使用父类的静态属性和静态方法,而无需重新定义。

代码示例:

class Car {
  static numWheels = 4;

  static getCarInfo() {
    return `This car has ${this.numWheels} wheels.`;
  }

  drive() {
    console.log(`The ${this.make} ${this.model} is driving.`);
  }
}

class ElectricCar extends Car {
  static numWheels = 4; // 子类继承父类静态属性

  static getCarInfo() { // 子类重写父类静态方法
    return `This electric car has ${this.numWheels} wheels and zero emissions.`;
  }

  drive() { // 子类重写父类实例方法
    console.log(`The ${this.make} ${this.model} is driving silently.`);
  }
}

const car1 = new Car("Tesla", "Model S");
const electricCar1 = new ElectricCar("Tesla", "Model X");

console.log(Car.getCarInfo()); // "This car has 4 wheels."
console.log(ElectricCar.getCarInfo()); // "This electric car has 4 wheels and zero emissions."
car1.drive(); // "The Tesla Model S is driving."
electricCar1.drive(); // "The Tesla Model X is driving silently."

在这个例子中,ElectricCar 子类继承了 Car 父类的静态属性和静态方法,这意味着它可以访问和使用这些属性和方法,而无需重新定义它们。

代码可维护性

让代码更易于维护和扩展

静态属性和静态方法可以帮助你提高代码的可维护性。你可以在父类中定义静态属性和静态方法,然后在子类中继承它们。这样,子类就可以使用父类的静态属性和静态方法,而无需重新定义。这可以减少代码冗余,使代码更容易维护和扩展。

代码示例:

class Car {
  static numWheels = 4;

  static getCarInfo() {
    return `This car has ${this.numWheels} wheels.`;
  }

  drive() {
    console.log(`The ${this.make} ${this.model} is driving.`);
  }
}

class ElectricCar extends Car {
  static