static

Baseline 已广泛支持

此特性已经非常成熟,并且适用于许多设备和浏览器版本。自 2016 年 3 月以来,它已在所有浏览器中可用。

static 关键字定义了一个类的静态方法或字段,或者一个静态初始化块(有关此用法的更多信息,请参阅链接)。静态属性不能直接通过类的实例访问。相反,它们是在类本身上访问的。

静态方法通常是实用工具函数,例如创建或克隆对象的函数,而静态属性对于缓存、固定配置或任何其他不需要在实例之间复制的数据非常有用。

注意: 在类的上下文中,MDN Web Docs 内容将术语属性和字段互换使用。

试一试

class ClassWithStaticMethod {
  static staticProperty = "someValue";
  static staticMethod() {
    return "static method has been called.";
  }
  static {
    console.log("Class static initialization block called");
  }
}

console.log(ClassWithStaticMethod.staticProperty);
// Expected output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// Expected output: "static method has been called."

语法

js
class ClassWithStatic {
  static staticField;
  static staticFieldWithInitializer = value;
  static staticMethod() {
    // …
  }
}

还有一些额外的语法限制

  • 静态属性(字段或方法)的名称不能是 prototype
  • 类字段(静态或实例)的名称不能是 constructor

描述

本页介绍类的公共静态属性,包括静态方法、静态访问器和静态字段。

公共静态特性使用 static 关键字声明。它们在类评估时使用 [[DefineOwnProperty]] 语义(本质上是 Object.defineProperty())添加到类构造函数中。它们再次从类构造函数中访问。

静态方法通常是实用工具函数,例如创建或克隆实例的函数。公共静态字段在您希望每个类只存在一次字段,而不是在您创建的每个类实例上都存在时非常有用。这对于缓存、固定配置或任何其他不需要在实例之间复制的数据非常有用。

静态字段名称可以是计算得出的。计算表达式中的 this 值是围绕类定义的 this,并且引用类的名称会导致 ReferenceError,因为类尚未初始化。awaityield 在此表达式中按预期工作。

静态字段可以有初始化器。没有初始化器的静态字段被初始化为 undefined。公共静态字段不会在子类上重新初始化,但可以通过原型链访问。

js
class ClassWithStaticField {
  static staticField;
  static staticFieldWithInitializer = "static field";
}

class SubclassWithStaticField extends ClassWithStaticField {
  static subStaticField = "subclass field";
}

console.log(Object.hasOwn(ClassWithStaticField, "staticField")); // true
console.log(ClassWithStaticField.staticField); // undefined
console.log(ClassWithStaticField.staticFieldWithInitializer); // "static field"
console.log(SubclassWithStaticField.staticFieldWithInitializer); // "static field"
console.log(SubclassWithStaticField.subStaticField); // "subclass field"

在字段初始化器中,this 指的是当前类(您也可以通过其名称访问),而 super 指的是基类构造函数。

js
class ClassWithStaticField {
  static baseStaticField = "base static field";
  static anotherBaseStaticField = this.baseStaticField;

  static baseStaticMethod() {
    return "base static method output";
  }
}

class SubClassWithStaticField extends ClassWithStaticField {
  static subStaticField = super.baseStaticMethod();
}

console.log(ClassWithStaticField.anotherBaseStaticField); // "base static field"
console.log(SubClassWithStaticField.subStaticField); // "base static method output"

表达式是同步评估的。您不能在初始化器表达式中使用 awaityield。(可以将初始化器表达式看作是隐式包装在一个函数中。)

静态字段初始化器和静态初始化块是逐个评估的。字段初始化器可以引用其上方字段的值,但不能引用其下方字段的值。所有静态方法都预先添加,并且可以访问,尽管如果它们引用了正在初始化的字段下方的字段,则调用它们可能不会按预期行为。

注意: 这对于私有静态字段更为重要,因为访问未初始化的私有字段会抛出 TypeError,即使私有字段是在下方声明的。(如果私有字段未声明,则会是早期的 SyntaxError。)

示例

在类中使用静态成员

以下示例演示了几件事

  1. 如何在类上定义静态成员(方法或属性)。
  2. 具有静态成员的类可以被子类化。
  3. 静态成员可以和不能如何调用。
js
class Triple {
  static customName = "Tripler";
  static description = "I triple any number you provide";
  static calculate(n = 1) {
    return n * 3;
  }
}

class SquaredTriple extends Triple {
  static longDescription;
  static description = "I square the triple of any number you provide";
  static calculate(n) {
    return super.calculate(n) * super.calculate(n);
  }
}

console.log(Triple.description); // 'I triple any number you provide'
console.log(Triple.calculate()); // 3
console.log(Triple.calculate(6)); // 18

const tp = new Triple();

console.log(SquaredTriple.calculate(3)); // 81 (not affected by parent's instantiation)
console.log(SquaredTriple.description); // 'I square the triple of any number you provide'
console.log(SquaredTriple.longDescription); // undefined
console.log(SquaredTriple.customName); // 'Tripler'

// This throws because calculate() is a static member, not an instance member.
console.log(tp.calculate()); // 'tp.calculate is not a function'

从另一个静态方法调用静态成员

为了在同一类的另一个静态方法中调用静态方法或属性,可以使用 this 关键字。

js
class StaticMethodCall {
  static staticProperty = "static property";
  static staticMethod() {
    return `Static method and ${this.staticProperty} has been called`;
  }
  static anotherStaticMethod() {
    return `${this.staticMethod()} from another static method`;
  }
}
StaticMethodCall.staticMethod();
// 'Static method and static property has been called'

StaticMethodCall.anotherStaticMethod();
// 'Static method and static property has been called from another static method'

从类构造函数和其他方法调用静态成员

静态成员不能使用非静态方法中的 this 关键字直接访问。您需要使用类名调用它们:CLASSNAME.STATIC_METHOD_NAME() / CLASSNAME.STATIC_PROPERTY_NAME,或者通过将方法作为 constructor 的属性来调用:this.constructor.STATIC_METHOD_NAME() / this.constructor.STATIC_PROPERTY_NAME

js
class StaticMethodCall {
  constructor() {
    console.log(StaticMethodCall.staticProperty); // 'static property'
    console.log(this.constructor.staticProperty); // 'static property'
    console.log(StaticMethodCall.staticMethod()); // 'static method has been called.'
    console.log(this.constructor.staticMethod()); // 'static method has been called.'
  }

  static staticProperty = "static property";
  static staticMethod() {
    return "static method has been called.";
  }
}

规范

规范
ECMAScript® 2026 语言规范
# sec-class-definitions

浏览器兼容性

另见