このページは、実験的な機能について説明しています。
パブリックフィールド宣言とプライベートフィールド宣言の両方は、JavaScriptの標準化委員会である TC39 で提案された実験的な機能(ステージ3)です。
ブラウザのサポートは限られていますが、Babel のようなシステムではビルドステップを経て機能を利用することができます。下記の互換性情報を参照してください。
クラスのプロパティはデフォルトで公開されており、クラスの外で調べたり変更したりすることができます。しかし、ハッシュ # 接頭辞を使ってプライベートなクラスフィールドを定義できるようにする実験的な提案が追加されました。
構文
class ClassWithPrivateField {
#privateField
}
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world'
}
}
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD
}
例
プライベートスタティックフィールド
プライベートフィールドは、クラスのコンストラクタ上でクラス宣言の内部からアクセスできます。
静的変数は静的メソッドからのみ呼び出せるという制限はまだあります。
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD
static publicStaticMethod() {
ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42
return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD
}
}
console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)
プライベートスタティックフィールドは、クラスの評価時にクラスのコンストラクタに追加されます。
プライベートスタティックフィールドには、プライベートスタティックフィールドを定義しているクラスのみが、そのフィールドにアクセスできるという出自制限があります。
これは、this を使用しているときに予期しない動作をする可能性があります。
class BaseClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD
static basePublicStaticMethod() {
this.#PRIVATE_STATIC_FIELD = 42
return this.#PRIVATE_STATIC_FIELD
}
}
class SubClass extends BaseClassWithPrivateStaticField { }
let error = null
try {
SubClass.basePublicStaticMethod()
} catch(e) { error = e}
console.assert(error instanceof TypeError)
プライベートインスタンスフィールド
プライベートインスタンスフィールドは # names (ハッシュネーム) で宣言され、これは # を先頭にした識別子です。この # は名前の一部で、宣言やアクセスにも使われます。
このカプセル化は言語によって強制されています。範囲外から # の名前を参照するのは構文エラーです。
class ClassWithPrivateField {
#privateField
constructor() {
this.#privateField = 42
this.#randomField = 444 // Syntax error
}
}
const instance = new ClassWithPrivateField()
instance.#privateField === 42 // Syntax error
プライベートメソッド
プライベートスタティックメソッド
プライベートスタティックメソッドは、パブリックと同様に、クラスのインスタンスではなく、クラス自体から呼び出されます。プライベートスタティックフィールドと同様に、クラス宣言の内部からのみアクセス可能です。
プライベートスタティックメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数、などがあります
class ClassWithPrivateStaticMethod {
static #privateStaticMethod() {
return 42
}
static publicStaticMethod1() {
return ClassWithPrivateStaticMethod.#privateStaticMethod();
}
static publicStaticMethod2() {
return this.#privateStaticMethod();
}
}
console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42);
console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42);
this を使用すると、予期しない動作が発生する可能性があります。次の例では、Derived.publicStaticMethod2() を呼び出そうとしたときに、this が 派生 クラス(Base クラスではない)を参照しており、上で述べたのと同じ "出自制限" を示します。
class Base {
static #privateStaticMethod() {
return 42;
}
static publicStaticMethod1() {
return Base.#privateStaticMethod();
}
static publicStaticMethod2() {
return this.#privateStaticMethod();
}
}
class Derived extends Base {}
console.log(Derived.publicStaticMethod1()); // 42
console.log(Derived.publicStaticMethod2()); // TypeError
プライベートインスタンスメソッド
プライベートインスタンスメソッドは、プライベートインスタンスフィールドと同様にアクセスが制限されているクラスインスタンスで利用できるメソッドです。
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world'
}
getPrivateMessage() {
return this.#privateMethod()
}
}
const instance = new ClassWithPrivateMethod()
console.log(instance.getPrivateMessage())
// expected output: "hello world"
プライベートインスタンスメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数のいずれかになります。プライベートなゲッターやセッターも可能です。
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✨"
仕様
| 仕様書 |
|---|
| Public and private instance fields FieldDefinition の定義 |
ブラウザの互換性
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Private class fields | Chrome 完全対応 74 | Edge 完全対応 79 | Firefox 未対応 なし | IE 未対応 なし | Opera 完全対応 62 | Safari 完全対応 14 | WebView Android 完全対応 74 | Chrome Android 完全対応 74 | Firefox Android 未対応 なし | Opera Android 完全対応 53 | Safari iOS 完全対応 14 | Samsung Internet Android 未対応 なし | nodejs 完全対応 12.0.0 |
凡例
- 完全対応
- 完全対応
- 未対応
- 未対応