概要: このチュートリアルでは、JavaScript のプライベートフィールドと、それらを効果的に使用する方法について学習します。
JavaScript プライベートフィールドの紹介
ES2022 では、クラスにプライベートフィールドを定義できます。プライベートフィールドを定義するには、フィールド名の前に#
記号を付けます。
たとえば、次の例は、プライベートフィールドradius
を持つCircle
クラスを定義しています。
class Circle {
#radius;
constructor(value) {
this.#radius = value;
}
get area() {
return Math.PI * Math.pow(this.#radius, 2);
}
}
Code language: JavaScript (javascript)
この例では
- まず、クラス本体にプライベートフィールド
#radius
を定義します。 - 次に、コンストラクタで引数を用いて
#radius
フィールドを初期化します。 - 次に、ゲッターメソッドで
#radius
プライベートフィールドにアクセスして円の面積を計算します。
次の例では、Circle
クラスの新しいインスタンスを作成し、その面積を計算しています。
let circle = new Circle(10);
console.log(circle.area); // 314.1592653589793
Code language: JavaScript (javascript)
#radius
はプライベートフィールドであるため、Circle
クラス内でのみアクセスできます。つまり、#radius
フィールドはCircle
クラスの外部からは見えません。
ゲッターとセッターを使用してプライベートフィールドにアクセスする
次の例では、radius
ゲッターとセッターを追加して#radius
プライベートフィールドへのアクセスを提供することにより、Circle
クラスを再定義しています。
class Circle {
#radius = 0;
constructor(radius) {
this.radius = radius; // calling setter
}
get area() {
return Math.PI * Math.pow(this.#radius, 2);
}
set radius(value) {
if (typeof value === 'number' && value > 0) {
this.#radius = value;
} else {
throw 'The radius must be a positive number';
}
}
get radius() {
return this.#radius;
}
}
Code language: JavaScript (javascript)
動作方法。
radius
セッターは、引数を#radius
プライベートフィールドに代入する前に、引数を検証します。引数が正の数でない場合、radius
セッターはエラーをスローします。radius
ゲッターは、#radius
プライベートフィールドの値を返します。- コンストラクタは
radius
セッターを呼び出して、引数を#radius
プライベートフィールドに代入します。
プライベートフィールドとサブクラス
プライベートフィールドは、定義されているクラス内でのみアクセス可能です。また、サブクラスからもアクセスできません。たとえば、次の例は、拡張するCylinder
クラスを定義していますCircle
クラス
class Cylinder extends Circle {
#height;
constructor(radius, height) {
super(radius);
this.#height = height;
// cannot access the #radius of the Circle class here
}
}
Code language: JavaScript (javascript)
Cylinder
クラスで#radius
プライベートフィールドにアクセスしようとすると、SyntaxError
が発生します。
in 演算子:プライベートフィールドの存在を確認する
クラス内でオブジェクトにプライベートフィールドがあるかどうかを確認するには、in
演算子を使用します。
fieldName in objectName
たとえば、次の例では、in
演算子を使用してcircle
オブジェクトに#radius
プライベートフィールドがあるかどうかを確認するhasRadius()
静的メソッドをCircle
クラスに追加しています。
class Circle {
#radius = 0;
constructor(radius) {
this.radius = radius;
}
get area() {
return Math.PI * Math.pow(this.radius, 2);
}
set radius(value) {
if (typeof value === 'number' && value > 0) {
this.#radius = value;
} else {
throw 'The radius must be a positive number';
}
}
get radius() {
return this.#radius;
}
static hasRadius(circle) {
return #radius in circle;
}
}
let circle = new Circle(10);
console.log(Circle.hasRadius(circle));
Code language: JavaScript (javascript)
出力
true
Code language: JavaScript (javascript)
静的プライベートフィールド
次の例は、静的プライベートフィールドの使用方法を示しています。
class Circle {
#radius = 0;
static #count = 0;
constructor(radius) {
this.radius = radius; // calling setter
Circle.#count++;
}
get area() {
return Math.PI * Math.pow(this.radius, 2);
}
set radius(value) {
if (typeof value === 'number' && value > 0) {
this.#radius = value;
} else {
throw 'The radius must be a positive number';
}
}
get radius() {
return this.#radius;
}
static hasRadius(circle) {
return #radius in circle;
}
static getCount() {
return Circle.#count;
}
}
let circles = [new Circle(10), new Circle(20), new Circle(30)];
console.log(Circle.getCount());
Code language: JavaScript (javascript)
動作方法。
まず、Circle
クラスにプライベート静的フィールド#count
を追加し、その値をゼロに初期化します。
static #count = 0;
Code language: JavaScript (javascript)
次に、コンストラクタで#count
を1増やします。
Circle.#count++;
Code language: JavaScript (javascript)
次に、#count
プライベート静的フィールドの値を返す静的メソッドを定義します。
static getCount() {
return Circle.#count;
}
Code language: JavaScript (javascript)
最後に、Circle
クラスのインスタンスを3つ作成し、count
の値をコンソールに出力します。
let circles = [new Circle(10), new Circle(20), new Circle(30)];
console.log(Circle.getCount());
Code language: JavaScript (javascript)
まとめ
- フィールド名を
#
記号で接頭辞として付けると、プライベートになります。 - プライベートフィールドは、クラス内でのみアクセス可能であり、クラス外またはサブクラスからはアクセスできません。
in
演算子を使用して、オブジェクトにプライベートフィールドがあるかどうかを確認します。