Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Private elements

Private elements are counterparts of the regular class elements which are public, includingclass fields, class methods, etc. Private elements get created by using a hash# prefix and cannot be legally referenced outside of the class. The privacy encapsulation of these class elements is enforced by JavaScript itself. The only way to access a private element is viadot notation, and you can only do so within the class that defines the private element.

Private elements were not native to the language before this syntax existed. In prototypal inheritance, its behavior may be emulated withWeakMap objects orclosures, but they can't compare to the# syntax in terms of ergonomics.

Note:On MDN, we avoid using the term "private property". Aproperty in JavaScript has a string or symbol key, and has attributes likewritable,enumerable, andconfigurable, but private elements have none. While private elements are accessed with the familiar dot notation, they cannot beproxied, enumerated, deleted, or interacted with using anyObject method.

Syntax

js
class ClassWithPrivate {  #privateField;  #privateFieldWithInitializer = 42;  #privateMethod() {    // …  }  static #privateStaticField;  static #privateStaticFieldWithInitializer = 42;  static #privateStaticMethod() {    // …  }}

There are some additional syntax restrictions:

  • All private identifiers declared within a class must be unique. The namespace is shared between static and instance elements. The only exception is when the two declarations define a getter-setter pair.
  • The private identifier cannot be#constructor.

Description

Most class elements have their private counterparts:

  • Private fields
  • Private methods
  • Private static fields
  • Private static methods
  • Private getters
  • Private setters
  • Private static getters
  • Private static setters

These features are collectively calledprivate elements. However,constructors cannot be private in JavaScript. To prevent classes from being constructed outside of the class, you have touse a private flag.

Private elements are declared with# names (pronounced "hash names"), which are identifiers prefixed with#. The hash prefix is an inherent part of the property name — you can draw relationship with the old underscore prefix convention_privateField — but it's not an ordinary string property, so you can't dynamically access it with thebracket notation.

It is a syntax error to refer to# names from outside of the class. It is also a syntax error to refer to private elements that were not declared in the class body, or to attempt to remove declared elements withdelete.

js
class ClassWithPrivateField {  #privateField;  constructor() {    delete this.#privateField; // Syntax error    this.#undeclaredField = 42; // Syntax error  }}const instance = new ClassWithPrivateField();instance.#privateField; // Syntax error

JavaScript, being a dynamic language, is able to perform this compile-time check because of the special hash identifier syntax, making it different from normal properties on the syntax level.

Note:Code run in the Chrome console can access private elements outside the class. This is a DevTools-only relaxation of the JavaScript syntax restriction.

If you access a private element from an object that doesn't have the element, aTypeError is thrown, instead of returningundefined as normal properties do.

js
class C {  #x;  static getX(obj) {    return obj.#x;  }}console.log(C.getX(new C())); // undefinedconsole.log(C.getX({})); // TypeError: Cannot read private member #x from an object whose class did not declare it

This example also illustrates that you can access private elements within static functions too, and on externally defined instances of the class.

You can use thein operator to check whether an externally defined object possesses a private element. This will returntrue if the private field or method exists, andfalse otherwise.

js
class C {  #x;  constructor(x) {    this.#x = x;  }  static getX(obj) {    if (#x in obj) return obj.#x;    return "obj must be an instance of C";  }}console.log(C.getX(new C("foo"))); // "foo"console.log(C.getX(new C(0.196))); // 0.196console.log(C.getX(new C(new Date()))); // the current date and timeconsole.log(C.getX({})); // "obj must be an instance of C"

Note a corollary of private names being always pre-declared and non-deletable: if you found that an object possesses one private element of the current class (either from atry...catch or anin check), it must possess all other private elements. An object possessing the private elements of a class generally means it was constructed by that class (althoughnot always).

Private elements are not part of theprototypical inheritance model since they can only be accessed within the current class's body and aren't inherited by subclasses. Private elements with the same name within different classes are entirely different and do not interoperate with each other. See them as external metadata attached to each instance, managed by the class. For this reason,structuredClone() does not clone private elements, andObject.freeze() andObject.seal() have no effect on private elements.

For more information on how and when private fields are initialized, seepublic class fields.

Examples

Private fields

Private fields include private instance fields and private static fields. Private fields are only accessible from inside the class declaration.

Private instance fields

Like their public counterparts, private instance fields:

  • are added before the constructor runs in a base class, or immediately aftersuper() is invoked in a subclass, and
  • are only available on instances of the class.
js
class ClassWithPrivateField {  #privateField;  constructor() {    this.#privateField = 42;  }}class Subclass extends ClassWithPrivateField {  #subPrivateField;  constructor() {    super();    this.#subPrivateField = 23;  }}new Subclass(); // In some dev tools, it shows Subclass {#privateField: 42, #subPrivateField: 23}

Note:#privateField from theClassWithPrivateField base class is private toClassWithPrivateField and is not accessible from the derivedSubclass.

Returning overriding object

A class's constructor can return a different object, which will be used as the newthis for the derived class constructor. The derived class may then define private fields on that returned object — meaning it is possible to "stamp" private fields onto unrelated objects.

js
class Stamper extends class {  // A base class whose constructor returns the object it's given  constructor(obj) {    return obj;  }} {  // This declaration will "stamp" the private field onto the object  // returned by the base class constructor  #stamp = 42;  static getStamp(obj) {    return obj.#stamp;  }}const obj = {};new Stamper(obj);// `Stamper` calls `Base`, which returns `obj`, so `obj` is// now the `this` value. `Stamper` then defines `#stamp` on `obj`console.log(obj); // In some dev tools, it shows {#stamp: 42}console.log(Stamper.getStamp(obj)); // 42console.log(obj instanceof Stamper); // false// You cannot stamp private elements twicenew Stamper(obj); // Error: Initializing an object twice is an error with private fields

Warning:This is a potentially very confusing thing to do. You are generally advised to avoid returning anything from the constructor — especially something unrelated tothis.

Private static fields

Like their public counterparts, private static fields:

  • are added to the class constructor at class evaluation time, and
  • are only available on the class itself.
js
class ClassWithPrivateStaticField {  static #privateStaticField = 42;  static publicStaticMethod() {    return ClassWithPrivateStaticField.#privateStaticField;  }}console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42

There is a restriction on private static fields: only the class which defines the private static field can access the field. This can lead to unexpected behavior when usingthis. In the following example,this refers to theSubclass class (not theClassWithPrivateStaticField class) when we try to callSubclass.publicStaticMethod(), and so causes aTypeError.

js
class ClassWithPrivateStaticField {  static #privateStaticField = 42;  static publicStaticMethod() {    return this.#privateStaticField;  }}class Subclass extends ClassWithPrivateStaticField {}Subclass.publicStaticMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it

This is the same if you call the method withsuper, becausesuper methods are not called with the super class asthis.

js
class ClassWithPrivateStaticField {  static #privateStaticField = 42;  static publicStaticMethod() {    // When invoked through super, `this` still refers to Subclass    return this.#privateStaticField;  }}class Subclass extends ClassWithPrivateStaticField {  static callSuperMethod() {    return super.publicStaticMethod();  }}Subclass.callSuperMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it

You are advised to always access private static fields through the class name, not throughthis, so inheritance doesn't break the method.

Private methods

Private methods include private instance methods and private static methods. Private methods are only accessible from inside the class declaration.

Private instance methods

Unlike their public counterparts, private instance methods:

  • are installed immediately before the instance fields are installed, and
  • are only available on instances of the class, not on its.prototype property.
js
class ClassWithPrivateMethod {  #privateMethod() {    return 42;  }  publicMethod() {    return this.#privateMethod();  }}const instance = new ClassWithPrivateMethod();console.log(instance.publicMethod()); // 42

Private instance methods may be generator, async, or async generator functions. Private getters and setters are also possible, and follow the same syntax requirements as their publicgetter andsetter counterparts.

js
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(); // 🎬hello world🛑

Unlike public methods, private methods are not accessible on the.prototype property of their class.

js
class C {  #method() {}  static getMethod(x) {    return x.#method;  }}console.log(C.getMethod(new C())); // [Function: #method]console.log(C.getMethod(C.prototype)); // TypeError: Receiver must be an instance of class C

Private static methods

Like their public counterparts, private static methods:

  • are added to the class constructor at class evaluation time, and
  • are only available on the class itself.
js
class ClassWithPrivateStaticMethod {  static #privateStaticMethod() {    return 42;  }  static publicStaticMethod() {    return ClassWithPrivateStaticMethod.#privateStaticMethod();  }}console.log(ClassWithPrivateStaticMethod.publicStaticMethod()); // 42

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

The same restriction previously mentioned for private static fields holds for private static methods, and similarly can lead to unexpected behavior when usingthis. In the following example, when we try to callSubclass.publicStaticMethod(),this refers to theSubclass class (not theClassWithPrivateStaticMethod class) and so causes aTypeError.

js
class ClassWithPrivateStaticMethod {  static #privateStaticMethod() {    return 42;  }  static publicStaticMethod() {    return this.#privateStaticMethod();  }}class Subclass extends ClassWithPrivateStaticMethod {}console.log(Subclass.publicStaticMethod()); // TypeError: Cannot read private member #privateStaticMethod from an object whose class did not declare it

Simulating private constructors

Many other languages include the capability to mark a constructor as private, which prevents the class from being instantiated outside of the class itself — you can only use static factory methods that create instances, or not be able to create instances at all. JavaScript does not have a native way to do this, but it can be accomplished by using a private static flag.

js
class PrivateConstructor {  static #isInternalConstructing = false;  constructor() {    if (!PrivateConstructor.#isInternalConstructing) {      throw new TypeError("PrivateConstructor is not constructable");    }    PrivateConstructor.#isInternalConstructing = false;    // More initialization logic  }  static create() {    PrivateConstructor.#isInternalConstructing = true;    const instance = new PrivateConstructor();    return instance;  }}new PrivateConstructor(); // TypeError: PrivateConstructor is not constructablePrivateConstructor.create(); // PrivateConstructor {}

Specifications

Specification
ECMAScript® 2026 Language Specification
# prod-PrivateIdentifier
ECMAScript® 2026 Language Specification
# prod-00OK517S

Browser compatibility

javascript.classes.private_class_fields

javascript.classes.private_class_fields_in

javascript.classes.private_class_methods

See also

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp