概要: このチュートリアルでは、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.1592653589793Code 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)出力
trueCode 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演算子を使用して、オブジェクトにプライベートフィールドがあるかどうかを確認します。