Class fields

Public and private field declarations are an experimental feature (stage 3) proposed at TC39, the JavaScript standards committee. Support in browsers is limited, but the feature can be used through a build step with systems like Babel. See the compat information below.

Campos públicos

Campos públicos y estáticos son propieades editables, enumerables, y configurables. A diferencia de su contraparte privada, estos participan en la herencia de prototipo.

Campos públicos estáticos

Public static fields are useful when you want a field to exist only once per class, not on every class instance you create. This is useful for caches, fixed configuration or any other data you don't need replicated across instances.

Public static fields are declared using the static keyword. They are added to the class constructor at the time of class evaluation using Object.defineProperty. They are accessed again from the class constructor.

class ClassWithStaticField {
  static staticField = 'static field';
}

console.log(ClassWithStaticField.staticField);
// expected output: "static field"​

Campos sin inicializadores son inicializados a undefined.

class ClassWithStaticField {
  static staticField;
}

console.assert(ClassWithStaticField.hasOwnProperty('staticField'));
console.log(ClassWithStaticField.staticField);
// expected output: "undefined"

Public static fields are not reinitialized on subclasses, but can be accessed via the prototype chain.

class ClassWithStaticField {
  static baseStaticField = 'base field';
}

class SubClassWithStaticField extends ClassWithStaticField {
  static subStaticField = 'sub class field';
}

console.log(SubClassWithStaticField.subStaticField);
// expected output: "sub class field"

console.log(SubClassWithStaticField.baseStaticField);
// expected output: "base field"

When initializing fields this refers to the class constructor. You can also reference it by name, and use super to get the superclass constructor if one exists.

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);
// expected output: "base static field"

console.log(SubClassWithStaticField.subStaticField);
// expected output: "base static method output"

Campos de instancia públicos

Public instance fields exist on every created instance of a class. By declaring a public field we can ensure the field is always present, and the class definition is more self-documenting.

Public instance fields are added with Object.defineProperty either at construction time in the base class (before the constructor body runs), or just after super() returns in a subclass.

class ClassWithInstanceField {
  instanceField = 'instance field';
}

const instance = new ClassWithInstanceField();
console.log(instance.instanceField);
// expected output: "instance field"

Fields without initializers are initialized to undefined.

class ClassWithInstanceField {
  instanceField;
}

const instance = new ClassWithInstanceField();
console.assert(instance.hasOwnProperty('instanceField'));
console.log(instance.instanceField);
// expected output: "undefined"

Like properties, field names may be computed.

const PREFIX = 'prefix';

class ClassWithComputedFieldName {
    [`${PREFIX}Field`] = 'prefixed field';
}

const instance = new ClassWithComputedFieldName();
console.log(instance.prefixField);
// expected output: "prefixed field"

When initializing fields this refers to the class instance under construction. Just as in public instance methods, if you're in a subclass you can access the superclass prototype using super.

class ClassWithInstanceField {
  baseInstanceField = 'base field';
  anotherBaseInstanceField = this.baseInstanceField;
  baseInstanceMethod() { return 'base method output'; }
}

class SubClassWithInstanceField extends ClassWithInstanceField {
  subInstanceField = super.baseInstanceMethod();
}

const base = new ClassWithInstanceField();
const sub = new SubClassWithInstanceField();

console.log(base.anotherBaseInstanceField);
// expected output: "base field"

console.log(sub.subInstanceField);
// expected output: "base method output"

Métodos públicos

Métodos públicos estáticos

The static keyword defines a static method for a class. Static methods aren't called on instances of the class. Instead, they're called on the class itself. These are often utility functions, such as functions to create or clone objects.

The static methods are added to the class constructor with Object.defineProperty at class evaluation time. These methods are writable, non-enumerable and configurable.

Métodos públicos de instancia

As the name implies, public instance methods are methods available on class instances.

class ClassWithPublicInstanceMethod {
  publicMethod() {
    return 'hello world';
  }
}

const instance = new ClassWithPublicInstanceMethod();
console.log(instance.publicMethod());
// expected output: "hello worl​d"

Public instance methods are added to the class prototype at the time of class evaluation using Object.defineProperty. They are writable, non-enumerable, and configurable.

You may make use of generator, async and async generator functions.

class ClassWithFancyMethods {
  *generatorMethod() { }
  async asyncMethod() { }
  async *asyncGeneratorMethod() { }
}

Inside instance methods, this refers to the instance itself. In subclasses, super lets you access the superclass prototype, allowing you to call methods from the superclass.

class BaseClass {
  msg = 'hello world';
  basePublicMethod() {
    return this.msg;
  }
}

class SubClass extends BaseClass {
  subPublicMethod() {
    return super.basePublicMethod();
  }
}

const instance = new SubClass();
console.log(instance.subPublicMethod());
// expected output: "hello worl​d"

Getters and setters are special methods that bind to a class property, and are called when that property is accessed or set. Use the get and set syntax to declare a public instance getter or setter.

class ClassWithGetSet {
  #msg = 'hello world';
  get msg() {
    return this.#msg;
  }
  set msg(x) {
    this.#msg = `hello ${x}`;
  }
}

const instance = new ClassWithGetSet();
console.log(instance.msg);
// expected output: "hello worl​d"

instance.msg = 'cake';
console.log(instance.msg);
// expected output: "hello cake"

Campos privados

Campos privados estáticos

Private fields are accessible on the class constructor from inside the class declaration itself.

The limitation of static variables being called by only static methods still holds.

class ClassWithPrivateStaticField {
  static #PRIVATE_STATIC_FIELD;

  static publicStaticMethod() {
    ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42;
    return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD;
  }
}

assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);

Private static fields are added to the class constructor at class evaluation time.

There is a provenance restriction on private static fields. Only the class which defines the private static field can access the field. This can lead to unexpected behaviour when using this

class BaseClassWithPrivateStaticField {
  static #PRIVATE_STATIC_FIELD;

  static basePublicStaticMethod() {
    this.#PRIVATE_STATIC_FIELD = 42;
    return this.#PRIVATE_STATIC_FIELD;
  }
}

class SubClass extends BaseClassWithPrivateStaticField { }

assertThrows(() => SubClass.basePublicStaticMethod(), TypeError);

Campos privados de instancia

Private instance fields are declared with # names ( pronounced "hash names"), which are identifiers prefixed with #. The # is a part of the name itself and is used for declaration and accessing as well.

The encapsulation is enforced by the language. It is a syntax error to refer to # names not in scope.

class ClassWithPrivateField {
  #privateField;
  
  constructor() {
    this.#privateField = 42;
    this.#randomField = 666; # Syntax error
  }
}

const instance = new ClassWithPrivateField();
instance.#privateField === 42; // Syntax error

Métodos privados

Métodos privados estáticos

Like their public equivalent, private static methods are called on the class, not instances of the class. Like private static fields, they are only accessible from inside the class declaration.

Private static methods may be generator, async and async generator functions.

class ClassWithPrivateStaticMethod {
    static #privateStaticMethod() {
        return 42;
    }

    static publicStaticMethod() {
        return ClassWithPrivateStaticMethod.#privateStaticMethod();
    }
}

assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);

Métodos privados de instancia

Private instance methods are methods available on class instances whose access is restricted in the same manner as private instance fields.

class ClassWithPrivateMethod {
  #privateMethod() {
    return 'hello world';
  }

  getPrivateMessage() {
      return #privateMethod();
  }
}

const instance = new ClassWithPrivateMethod();
console.log(instance.getPrivateMessage());
// expected output: "hello worl​d"

Private instance methods may be generator, async or async generator functions. Private getters and setters are also possible:

class ClassWithPrivateAccessor {
  #message;

  get #decoratedMessage() {
    return `✨${this.#message}✨`;
  }
  set #decoratedMessage(msg) {
    this.#message = msg;
  }

  constructor() {
    this.#decoratedMessage = 'hello world';
    console.log(this.#decoratedMessage);
  }
}

new ClassWithPrivateAccessor();
// expected output: "✨hello worl​d✨"

Especificaciones

Especificación Estado Comentario
FieldDefinition production Stage 3

Compatibilidad de navegadores

Campos públicos de clse

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome para AndroidFirefox para AndroidOpera para AndroidSafari en iOSSamsung InternetNode.js
Public class fieldsChrome Soporte completo 72Edge Sin soporte NoFirefox Soporte completo 69IE Sin soporte NoOpera Soporte completo 60Safari Sin soporte NoWebView Android Soporte completo 72Chrome Android Soporte completo 72Firefox Android Sin soporte NoOpera Android Soporte completo 51Safari iOS Sin soporte NoSamsung Internet Android Sin soporte Nonodejs Soporte completo 12.0.0

Leyenda

Soporte completo  
Soporte completo
Sin soporte  
Sin soporte

Campos privados de clase

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome para AndroidFirefox para AndroidOpera para AndroidSafari en iOSSamsung InternetNode.js
Private class fieldsChrome Soporte completo 74Edge Sin soporte NoFirefox Sin soporte NoIE Sin soporte NoOpera Soporte completo 62Safari Sin soporte NoWebView Android Soporte completo 74Chrome Android Soporte completo 74Firefox Android Sin soporte NoOpera Android Soporte completo 53Safari iOS Sin soporte NoSamsung Internet Android Sin soporte Nonodejs Soporte completo 12.0.0

Leyenda

Soporte completo  
Soporte completo
Sin soporte  
Sin soporte

Ver también