From 58ba52e1264f4062cdc8219ceff95bb1a914a383 Mon Sep 17 00:00:00 2001
From: "Eric A. Meyer" Class properties are public by default and can be examined or modified outside the
+ Class properties are public by default, and can be examined or modified outside the
class. There is however a
- stage 3 proposal to allow defining private class fields using a hash
- #
prefix.#
prefix. The privacy encapsulation of these class features is
+ enforced by JavaScript itself.
class ClassWithPrivateField { - #privateField + #privateField; } class ClassWithPrivateMethod { #privateMethod() { - return 'hello world' + return 'hello world'; } } class ClassWithPrivateStaticField { - static #PRIVATE_STATIC_FIELD + static #PRIVATE_STATIC_FIELD; +} + +class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 'hello world'; + } }
Private instance fields are declared with # names (pronounced
+ "hash names"), which are identifiers prefixed with #
. The
+ #
is a part of the name itself. Private fields are accessible on
+ the class constructor from inside the class
+ declaration itself. They are used for declaration of field names as well
+ as for accessing a field’s value.
It is a syntax error to refer to #
names from out of scope.
+ It is also a syntax error to refer to private fields
+ that were not declared before they were called, or to attempt to remove
+ declared fields with delete
.
class ClassWithPrivateField { + #privateField; + + constructor() { + this.#privateField = 42; + delete this.#privateField; // Syntax error + this.#undeclaredField = 444; // Syntax error + } +} -+ +Private fields are accessible on the class constructor from inside the class - declaration itself.
+const instance = new ClassWithPrivateField() +instance.#privateField === 42; // Syntax error +
Like public fields, private fields are added at construction time in a base class, or at the point where super()
is invoked in a subclass.
The limitation of static variables being called by only static methods still holds.
+class ClassWithPrivateField { + #privateField; + + constructor() { + this.#privateField = 42; + } +} + +class SubClass extends ClassWithPrivateField { + #subPrivateField; + + constructor() { + super(); + this.#subPrivateField = 23; + } +} + +new SubClass(); +// SubClass {#privateField: 42, #subPrivateField: 23} ++ + +
Private static fields are added to the class constructor at class evaluation time. + The limitation of static variables being called by only static methods still holds.
class ClassWithPrivateStaticField { - static #PRIVATE_STATIC_FIELD + static #PRIVATE_STATIC_FIELD; static publicStaticMethod() { - ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42 - return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD + ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42; + return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD; } } -console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)- -
Private static fields are added to the class constructor at class evaluation time.
+console.log(ClassWithPrivateStaticField.publicStaticMethod() === 42); +// true + -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 behavior when using this
.
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 behavior when using this
.
+ In the following example, this
refers to the SubClass
class (not
+ the BaseClassWithPrivateStaticField
class) when we try to call
+ SubClass.basePublicStaticMethod()
, and so causes a TypeError
.
class BaseClassWithPrivateStaticField { - static #PRIVATE_STATIC_FIELD + static #PRIVATE_STATIC_FIELD; static basePublicStaticMethod() { - this.#PRIVATE_STATIC_FIELD = 42 - return this.#PRIVATE_STATIC_FIELD + this.#PRIVATE_STATIC_FIELD = 42; + return this.#PRIVATE_STATIC_FIELD; } } -class SubClass extends BaseClassWithPrivateStaticField { } +class SubClass extends BaseClassWithPrivateStaticField { }; -let error = null +let error = null; try { SubClass.basePublicStaticMethod() -} catch(e) { error = e} +} catch(e) { error = e}; -console.assert(error instanceof TypeError) +console.log(error instanceof TypeError); +// true +console.log(error); +// TypeError: Cannot write private member #PRIVATE_STATIC_FIELD +// to an object whose class did not declare it-
Private instance fields are declared with # names (pronounced
- "hash names"), which are identifiers prefixed with #
. The
- #
is a part of the name itself. It is used for declaration and accessing as
- well.
The encapsulation is enforced by the language. It is a syntax error to refer to
- #
names from out of scope.
class ClassWithPrivateField { - #privateField +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 this.#privateMethod(); + } +} + +const instance = new ClassWithPrivateMethod(); +console.log(instance.getPrivateMessage()); +// hello world+ +Private instance methods may be generator, async, or async generator functions. Private + getters and setters are also possible, although not in generator, async, or + async generator forms.
+ +class ClassWithPrivateAccessor { + #message; + + get #decoratedMessage() { + return `🎬${this.#message}🛑`; + } + set #decoratedMessage(msg) { + this.#message = msg; + } constructor() { - this.#privateField = 42 - this.#randomField = 444 // Syntax error + this.#decoratedMessage = 'hello world'; + console.log(this.#decoratedMessage); } } -const instance = new ClassWithPrivateField() -instance.#privateField === 42 // Syntax error +new ClassWithPrivateAccessor(); +// 🎬hello world🛑-Private methods
-Private static methods
Like their public equivalent, private static methods are called on the class itself, 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 + return 42; } static publicStaticMethod1() { @@ -125,15 +207,20 @@-Private static methods
} } -console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); -console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42); +console.log(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); +// true +console.log(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42); +// trueThis can lead to unexpected behavior when using
+this
. In - the following examplethis
refers to theDerived
class (not - theBase
class) when we try to call -Derived.publicStaticMethod2()
, and thus exhibits the same "provenance - restriction" as mentioned above:Private static methods may be generator, async, and async generator functions.
+ +The same provenance restriction previously mentioned for private static fields holds + for private static methods, and similarly can lead to unexpected behavior when using +
this
. + In the following example, when we try to callDerived.publicStaticMethod2()
, +this
refers to theDerived
class (not + theBase
class) and so causes aTypeError
.class Base { static #privateStaticMethod() { @@ -149,67 +236,39 @@-Private static methods
class Derived extends Base {} -console.log(Derived.publicStaticMethod1()); // 42 -console.log(Derived.publicStaticMethod2()); // TypeError +console.log(Derived.publicStaticMethod1()); +// 42 +console.log(Derived.publicStaticMethod2()); +// TypeError: Cannot read private member #privateStaticMethod +// from an object whose class did not declare itPrivate instance methods
- -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 this.#privateMethod() - } -} - -const instance = new ClassWithPrivateMethod() -console.log(instance.getPrivateMessage()) -// expected output: "hello world"- -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 world✨" -Specifications
-{{Specifications}} +
Specification | +
---|
{{SpecName('Public and private instance fields', '#prod-FieldDefinition', + 'FieldDefinition')}} | +
{{Compat}}
+{{Compat("javascript.classes.private_class_fields")}}
Note: This page describes experimental features.
+This page describes experimental features.
-Both public and private field declarations are an Both Public and private field declarations are an experimental feature (stage 3) proposed at TC39, the JavaScript standards committee.
@@ -275,17 +274,27 @@Specification | +
---|
{{SpecName('Public and private instance fields', '#prod-FieldDefinition', + 'FieldDefinition')}} | +
{{Compat}}
+{{Compat("javascript.classes.public_class_fields")}}
It’s common to want to make fields or methods private, but JavaScript has lacked such a feature since its inception. Conventions have arisen — such as prefixing fields and methods that should be treated as private with an underscore, like _hidden
— but these are merely conventions. The underscored features are still fully public.
Private class features deliver truly private fields and methods, with that privacy enforced by the language instead of convention. This confers benefits such as avoiding naming collisions between class features and the rest of the code base, and allowing classes to expose a very small interface to the rest of the code.
+ + +To understand how private fields work, let’s first consider a class that has only public fields, but uses the constructor to encapsulate data—a somewhat common technique, even if it is a bit of a hack. The following class creates a basic count that accepts a starting number, allows that number to be increased or decreased, and can be reset to the original starting value or any other value.
+ ++class PublicCounter { + constructor(start = 0) { + let _count = start; + let _init = start; + this.increase = (x = 1) => _count += x; + this.decrease = (x = 1) => _count -= x; + this.reset = (x = _init) => _count = x; + this.getCount = () => _count; + } + get current() { + return this.getCount(); + } +} ++ + + +
The idea here is that once a new counter of this type is spawned, its starting value and its current value are not available to code outside the counter. The only way to modify the value of _count
is through the defined methods, such as increase()
and reset()
. Similarly, _init
can’t be modified, because there are no methods inside the class to do so, and outside code is unable to reach it.
Here’s the same idea, only this time, we’ll use private fields.
+ ++class PrivateCounter { + #count; + #init; + constructor(start = 0) { + this.#init = start; + this.reset(start); + } + increase(x = 1) {this.#count += x;} + decrease(x = 1) {this.#count -= x;} + reset(x = this.#init) {this.#count = x;} + get current() { + return this.#count; + } +} + +let total = new PrivateCounter(7); +console.log(total.current); // expected output: 7 +total.increase(); // #count now = 8 +total.increase(5); // #count now = 13 +console.log(total.current); // expected output: 13 +total.reset(); // #count now = 7 ++ +
The “hash mark” (#
) is what marks a field as being private. It also prevents private fields and property names from ever being in conflict: private names must start with #
, whereas property names can never start that way.
Having established the private fields, they act as we saw in the public example. The only way to change the #count
value is via the publicly available methods like decrease()
, and because (in this example) there are no defined ways to alter it, the #init
value is immutable. It’s set when a new PrivateCounter
is constructed, and can never be changed thereafter.
It’s also the case that you cannot read a private value directly from code outside the class object. Consider:
+ ++let score = new PrivateCounter(); // #count and #init are now both 0 +score.increase(100); +console.log(score.current); + // output: 100 +console.log(score.#count); + // output: + // "Uncaught SyntaxError: Private field '#count' must be declared in an enclosing class" ++ +
If you wish to read private data from a class, you must first invent a method to return it. We had already done that with the current()
getter that returns the current value of #count
, but #init
is locked away. Unless we add something like a getInit()
method to the class, we can’t even see the initial value from outside the class, let alone alter it, and the compiler will throw a fit if we try.
What are the other restrictions around private fields? For one, you can’t refer to a private field you didn’t previously define. You might be used to inventing new fields on the fly in JavaScript, but that just won’t fly with private fields. + +
+class BadIdea { + constructor(arg) { + this.#init = arg; // syntax error occurs here + #startState = arg; // syntax error would also occur here + } // because private fields weren’t defined +} // before being referenced ++ +
You can’t define the same name twice in a single class, and you can’t delete private fields.
+ ++class BadIdeas { + #firstName; + #firstName; // syntax error occurs here + #lastName; + constructor() { + delete this.#lastName; // also a syntax error + } +} ++ +
And you can have static private fields, for things you want to be both private and set in stone at construction.
+ ++class colorMixer { + static #red = "rgba(1,0,0,1)"; + static #green = "rgba(0,1,0,1)"; + static #blue = "rgba(0,0,1,1)"; + #mixedColor; + constructor() { + … + } +} ++ +
There is another limitation: you can’t declare private fields or methods via object literals. You might be used to something like this:
+ ++var planet = { + name: 'Terra', + radiusKm: 6371, + radiusMiles: 3959 +}; ++ +
If you try to include a private class feature when doing this, an error will be thrown.
+ + ++var planet = { + name: 'Terra', + radiusKm: 6371, + radiusMiles: 3959, + #secret: 'central inner core' +}; +// result: +// "Uncaught SyntaxError: Unexpected identifier" ++ + + +
Just like private fields, private methods are marked with a leading #
and cannot be accessed from outside their class. They’re useful when you have something complex that the class needs to do internally, but it’s something that no other part of the code should be allowed to call.
For example, imagine creating HTML custom elements that should do something somewhat complicated when clicked/tapped/otherwise activated. Furthermore, the somewhat complicated things that happen when the element is clicked should be restricted to this class, because no other part of the JavaScript will (or should) ever access it. Therefore, something like:
+ ++class CustomClick extends HTMLElement { + #handleClicked() { + // do complicated stuff in here + } + constructor() { + super(); + this.#handleClicked(); + } + connectedCallback() { + this.addEventListener('click', this.#handleClicked) + } +} + +customElements.define('chci-interactive', CustomClick); ++ +
This can also be done for getters and setters, which is useful in any situation where you want to only get or set things from within the same class. As with fields and methods, prefix the name of the getter/setter with #
.
+class Counter extends HTMLElement { + #xValue = 0; + get #x() { return #xValue; } + set #x(value) { + this.#xValue = value; + window.requestAnimationFrame(this.#render.bind(this)); + } + #clicked() { + this.#x++; + } + constructor() { + super(); + this.onclick = this.#clicked.bind(this); + } + connectedCallback() { this.#render(); } + #render() { + this.textContent = this.#x.toString(); + } +} + +customElements.define('num-counter', Counter); ++ +
In this case, pretty much every field and method is private to the class. Thus, it presents an interface to the rest of the code that’s essentially just like a built-in HTML element. No other part of the JavaScript has the power to affect any of its internals.
+ +{{Compat("javascript.classes.private_class_fields")}}
+ From 8f6fce497c45a5700e0bb84cff9fcb1d2deb6cef Mon Sep 17 00:00:00 2001 From: "Eric A. Meyer"class PublicCounter { - constructor(start = 0) { - let _count = start; - let _init = start; - this.increase = (x = 1) => _count += x; - this.decrease = (x = 1) => _count -= x; - this.reset = (x = _init) => _count = x; - this.getCount = () => _count; - } - get current() { - return this.getCount(); - } + constructor(start = 0) { + let _count = start; + let _init = start; + this.increase = (x = 1) => _count += x; + this.decrease = (x = 1) => _count -= x; + this.reset = (x = _init) => _count = x; + this.getCount = () => _count; + } + get current() { + return this.getCount(); + } }@@ -41,18 +41,18 @@
class PrivateCounter { - #count; - #init; - constructor(start = 0) { - this.#init = start; - this.reset(start); - } - increase(x = 1) {this.#count += x;} - decrease(x = 1) {this.#count -= x;} - reset(x = this.#init) {this.#count = x;} - get current() { - return this.#count; - } + #count; + #init; + constructor(start = 0) { + this.#init = start; + this.reset(start); + } + increase(x = 1) { this.#count += x; } + decrease(x = 1) { this.#count -= x; } + reset(x = this.#init) { this.#count = x; } + get current() { + return this.#count; + } } let total = new PrivateCounter(7); @@ -65,7 +65,7 @@-Private Fields
The “hash mark” (
-#
) is what marks a field as being private. It also prevents private fields and property names from ever being in conflict: private names must start with#
, whereas property names can never start that way.Having established the private fields, they act as we saw in the public example. The only way to change the
+#count
value is via the publicly available methods likedecrease()
, and because (in this example) there are no defined ways to alter it, the#init
value is immutable. It’s set when a newPrivateCounter
is constructed, and can never be changed thereafter.Having declared the private fields, they act as we saw in the public example. The only way to change the
#count
value is via the publicly available methods likedecrease()
, and because (in this example) there are no defined ways to alter it, the#init
value is immutable. It’s set when a newPrivateCounter
is constructed, and can never be changed thereafter.It’s also the case that you cannot read a private value directly from code outside the class object. Consider:
@@ -73,13 +73,13 @@Private Fields
let score = new PrivateCounter(); // #count and #init are now both 0 score.increase(100); console.log(score.current); - // output: 100 + // output: 100 console.log(score.#count); - // output: - // "Uncaught SyntaxError: Private field '#count' must be declared in an enclosing class" + // output: + // "Uncaught SyntaxError: Private field '#count' must be declared in an enclosing class"
If you wish to read private data from a class, you must first invent a method to return it. We had already done that with the current()
getter that returns the current value of #count
, but #init
is locked away. Unless we add something like a getInit()
method to the class, we can’t even see the initial value from outside the class, let alone alter it, and the compiler will throw a fit if we try.
If you wish to read private data from outside a class, you must first invent a method or other function to return it. We had already done that with the current()
getter that returns the current value of #count
, but #init
is locked away. Unless we add something like a getInit()
method to the class, we can’t even see the initial value from outside the class, let alone alter it, and the compiler will throw a fit if we try.
What are the other restrictions around private fields? For one, you can’t refer to a private field you didn’t previously define. You might be used to inventing new fields on the fly in JavaScript, but that just won’t fly with private fields. @@ -196,6 +196,14 @@
In this case, pretty much every field and method is private to the class. Thus, it presents an interface to the rest of the code that’s essentially just like a built-in HTML element. No other part of the JavaScript has the power to affect any of its internals.
+{{Compat("javascript.classes.private_class_fields")}}
From 9b6813cc49a0c9a4afbcb263033c29e66d4462eb Mon Sep 17 00:00:00 2001 From: "Eric A. Meyer"Private class features deliver truly private fields and methods, with that privacy enforced by the language instead of convention. This confers benefits such as avoiding naming collisions between class features and the rest of the code base, and allowing classes to expose a very small interface to the rest of the code.
-To understand how private fields work, let’s first consider a class that has only public fields, but uses the constructor to encapsulate data—a somewhat common technique, even if it is a bit of a hack. The following class creates a basic count that accepts a starting number, allows that number to be increased or decreased, and can be reset to the original starting value or any other value.
@@ -79,7 +80,7 @@If you wish to read private data from outside a class, you must first invent a method or other function to return it. We had already done that with the current()
getter that returns the current value of #count
, but #init
is locked away. Unless we add something like a getInit()
method to the class, we can’t even see the initial value from outside the class, let alone alter it, and the compiler will throw a fit if we try.
If you wish to read private data from outside a class, you must first invent a method or other function to return it. We had already done that with the current()
getter that returns the current value of #count
, but #init
is locked away. Unless we add something like a getInit()
method to the class, we can’t even see the initial value from outside the class, let alone alter it, and the compiler will throw errors if we try.
What are the other restrictions around private fields? For one, you can’t refer to a private field you didn’t previously define. You might be used to inventing new fields on the fly in JavaScript, but that just won’t fly with private fields. @@ -145,11 +146,11 @@
Just like private fields, private methods are marked with a leading #
and cannot be accessed from outside their class. They’re useful when you have something complex that the class needs to do internally, but it’s something that no other part of the code should be allowed to call.
For example, imagine creating HTML custom elements that should do something somewhat complicated when clicked/tapped/otherwise activated. Furthermore, the somewhat complicated things that happen when the element is clicked should be restricted to this class, because no other part of the JavaScript will (or should) ever access it. Therefore, something like:
+For example, imagine creating HTML custom elements that should do something somewhat complicated when clicked/tapped/otherwise activated. Furthermore, the somewhat complicated things that happen when the element is clicked should be restricted to this class, because no other part of the JavaScript will (or should) ever access it. Therefore, something like:
class CustomClick extends HTMLElement { @@ -206,5 +207,5 @@See also
Browser compatibility
-{{Compat("javascript.classes.private_class_fields")}}
+{{Compat}}
diff --git a/files/en-us/web/javascript/reference/classes/private_class_fields/index.html b/files/en-us/web/javascript/reference/classes/private_class_fields/index.html index 8b7b7b26df99ed5..33256c638eab18b 100644 --- a/files/en-us/web/javascript/reference/classes/private_class_fields/index.html +++ b/files/en-us/web/javascript/reference/classes/private_class_fields/index.html @@ -6,6 +6,7 @@ - Private - JavaScript - Language feature +browser-compat: javascript.classes.private_class_fields ---{{JsSidebar("Classes")}}@@ -15,7 +16,7 @@#
prefix. The privacy encapsulation of these class features is enforced by JavaScript itself. -Basic Syntax
+Syntax
class ClassWithPrivateField { #privateField; @@ -54,7 +55,7 @@Private instance fields
that were not declared before they were called, or to attempt to remove declared fields withdelete
. -class ClassWithPrivateField { +class ClassWithPrivateField { #privateField; constructor() { @@ -111,7 +112,7 @@-Private static fields
There is a provenance restriction on private static fields: Only the class which +
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 using
this
. In the following example,this
refers to theSubClass
class (not theBaseClassWithPrivateStaticField
class) when we try to call @@ -215,7 +216,7 @@Private static methods
Private static methods may be generator, async, and async generator functions.
-The same provenance restriction previously mentioned for private static fields holds +
The same restriction previously mentioned for private static fields holds for private static methods, and similarly can lead to unexpected behavior when using
this
. In the following example, when we try to callDerived.publicStaticMethod2()
, @@ -246,23 +247,11 @@Private static methods
Specifications
-
Specification | -
---|
{{SpecName('Public and private instance fields', '#prod-FieldDefinition', - 'FieldDefinition')}} | -
{{Compat("javascript.classes.private_class_fields")}}
+{{Compat}}
This page describes experimental features.
+Note: This page describes experimental features.
-Both Public and private field declarations are an Both public and private field declarations are an experimental feature (stage 3) proposed at TC39, the JavaScript standards committee.
@@ -274,23 +275,11 @@Specification | -
---|
{{SpecName('Public and private instance fields', '#prod-FieldDefinition', - 'FieldDefinition')}} | -
{{Compat("javascript.classes.public_class_fields")}}
+{{Compat}}
And you can have static private fields, for things you want to be both private and set in stone at construction.
- --class colorMixer { - static #red = "rgba(1,0,0,1)"; - static #green = "rgba(0,1,0,1)"; - static #blue = "rgba(0,0,1,1)"; - #mixedColor; - constructor() { - … - } -} --
There is another limitation: you can’t declare private fields or methods via object literals. You might be used to something like this:
@@ -144,6 +130,20 @@+Private fields
// "Uncaught SyntaxError: Unexpected identifier"
On the other hand, you can have static private fields, for things you want to be both private and set in stone at construction.
+ ++class colorMixer { + static #red = "rgba(1,0,0,1)"; + static #green = "rgba(0,1,0,1)"; + static #blue = "rgba(0,0,1,1)"; + #mixedColor; + constructor() { + … + } +} ++
Class properties are public by default, and can be examined or modified outside the
- class. There is however a
- stage 3 proposal to allow private class features by using a hash
- #
prefix. The privacy encapsulation of these class features is
+
Class properties are {{ jsxref('Classes/Public_class_fields','public') }} by default, but private class members can be created
+ by using a hash #
prefix. The privacy encapsulation of these class features is
enforced by JavaScript itself.
{{Specifications}}
Note: This page describes experimental features.
- -Both 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.
-Both static and instance public fields are writable, enumerable, and configurable - properties. As such, unlike their private counterparts, they participate in prototype + properties. As such, unlike their {{ jsxref('Classes/Private_class_fields','private counterparts') }}, they participate in prototype inheritance.
{{Specifications}}
Class properties are {{ jsxref('Classes/Public_class_fields','public') }} by default, but private class members can be created +
Class fields are {{ jsxref('Classes/Public_class_fields','public') }} by default, but private class members can be created
by using a hash #
prefix. The privacy encapsulation of these class features is
enforced by JavaScript itself.
Both static and instance public fields are writable, enumerable, and configurable - properties. As such, unlike their {{ jsxref('Classes/Private_class_fields','private counterparts') }}, they participate in prototype +
Both static and instance public fields are writable, enumerable, and configurable. + As such, unlike their {{ jsxref('Classes/Private_class_fields','private counterparts') }}, they participate in prototype inheritance.
Warning: 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.
-With the JavaScript field declaration syntax, the above example can be written as: