プライベートクラスフィールド

このページは、実験的な機能について説明しています。

パブリックフィールド宣言とプライベートフィールド宣言の両方は、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 worl​d"

プライベートインスタンスメソッドは、ジェネレーター関数、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 worl​d✨"

仕様

仕様書
Public and private instance fields
FieldDefinition の定義

ブラウザの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
Private class fieldsChrome 完全対応 74Edge 完全対応 79Firefox 未対応 なしIE 未対応 なしOpera 完全対応 62Safari 完全対応 14WebView Android 完全対応 74Chrome Android 完全対応 74Firefox Android 未対応 なしOpera Android 完全対応 53Safari iOS 完全対応 14Samsung Internet Android 未対応 なしnodejs 完全対応 12.0.0

凡例

完全対応  
完全対応
未対応  
未対応

関連情報