ES6 クラス プライベートプロパティ 解説
JavaScript ES6 クラスにおけるプライベートプロパティ
JavaScript ES6 では、クラスのメンバーとして プライベートプロパティ を定義することができるようになりました。これにより、クラス内部でのみアクセス可能な変数を確保し、カプセル化を強化することができます。
構文
class MyClass {
#privateProperty = 'private value';
publicMethod() {
console.log(this.#privateProperty); // アクセス可能
}
}
重要なポイント
- 継承: プライベートプロパティは、クラスを継承しても子クラスからアクセスできません。
- メソッドからのアクセス: プライベートプロパティにアクセスするには、クラスのメソッド内から参照する必要があります。
- アクセス制限: プライベートプロパティは、クラスの内部からしかアクセスできません。クラスの外からは直接参照することができません。
- ハッシュタグ (#): プライベートプロパティを識別するために、プロパティ名の前にハッシュタグを使用します。
例
class Person {
#name;
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
getName() {
return this.#name;
}
getAge() {
return this.#age;
}
}
c onst john = new Person('John Doe', 30);
console.log(john.getName()); // John Doe
console.log(john.#name); // Error: Cannot access private member '#name'
利点
- セキュリティ: プライベートプロパティを外部からアクセスできないようにすることで、セキュリティリスクを軽減することができます。
- 保守性: プライベートプロパティの変更がクラスの外部に影響を与えないため、コードの変更や修正が容易になります。
- カプセル化: プライベートプロパティを使用することで、クラスの内部状態を外部から直接変更されることを防ぎ、コードの信頼性を向上させることができます。
JavaScript ES6 クラスのプライベートプロパティ: コード例と解説
プライベートプロパティとは?
JavaScript ES6で導入されたプライベートプロパティは、クラス内部でのみアクセス可能な変数です。クラスの外部から直接アクセスすることはできず、カプセル化を強化する上で非常に重要な概念です。
コード例とその解説
class Person {
#name; // プライベートプロパティ
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
// パブリックなメソッド (外部からアクセス可能)
greet() {
console.log(`こんにちは、私は${this.#name}です。${this.#age}歳です。`);
}
}
// Personクラスのインスタンスを作成
const taro = new Person('太郎', 30);
// パブリックなメソッドを使ってプライベートプロパティにアクセス
taro.greet(); // 出力: こんにちは、私は太郎です。30歳です。
// プライベートプロパティに直接アクセスしようとするとエラーになる
console.log(taro.#name); // Error: Cannot access private member '#name'
コードの解説
- クラスの定義
Person
というクラスを定義します。 - プライベートプロパティの宣言
#name
と#age
がプライベートプロパティです。ハッシュ記号(#
)で始まるのが特徴です。 - コンストラクタ
インスタンスが作成されるときに呼ばれるメソッドです。引数で受け取ったname
とage
をプライベートプロパティに代入します。 - パブリックなメソッド
greet()
メソッドは外部からアクセスできるメソッドです。内部でプライベートプロパティ#name
と#age
を使って挨拶文を出力します。 - インスタンスの作成
new Person('太郎', 30)
でPerson
クラスのインスタンスtaro
を作成します。 - パブリックメソッドの呼び出し
taro.greet()
でgreet()
メソッドを呼び出し、プライベートプロパティにアクセスして挨拶文を出力します。 - プライベートプロパティへの直接アクセス
taro.#name
のようにプライベートプロパティに直接アクセスしようとするとエラーになります。
プライベートプロパティのメリット
- 保守性の向上
プライベートプロパティを変更しても、外部のコードに影響を与えにくいので、コードの変更が容易になります。 - カプセル化
クラスの内部状態を外部から隠蔽し、意図しない変更を防ぎます。
JavaScript ES6のプライベートプロパティは、クラスの内部状態を安全に管理するための重要な機能です。この機能を効果的に活用することで、より堅牢で保守性の高いコードを作成することができます。
- 継承
プライベートプロパティは、子クラスから継承できません。 - アクセサー
プライベートプロパティへのアクセスを制御するために、getterとsetterを使用できます。 - プライベートメソッド
プライベートプロパティと同様に、クラス内部でのみ使用できるメソッドを定義できます。
さらに詳しく知りたい方へ
MDN Web Docsの「プライベートプロパティ」のページが詳しいです。
- プライベートプロパティは、JavaScriptのオブジェクト指向プログラミングにおいて、カプセル化を実現するための重要な要素です。
- 上記のコード例は、プライベートプロパティの基本的な使い方を示したものです。実際の開発では、より複雑なクラス設計やアクセサーの利用など、様々なパターンが考えられます。
アンダースコア(_)を先頭に付ける
- 強制力がない:リンターやIDEの警告で抑止することはできますが、厳密には外部からアクセスを禁止することはできません。
- 非公式な慣習:変数名にアンダースコアを付けることで、"プライベート"であることを示すという暗黙の了解に基づいています。
- 最もシンプルな方法
class Person {
_name; // プライベートな名前を示す
constructor(name) {
this._name = name;
}
}
クロージャを利用する
- 外部からアクセスできない:変数を関数の内部で定義することで、外部から直接アクセスできないようにします。
- 関数スコープを利用
function createPerson(name) {
let _name = name; // プライベート変数
return {
getName: function() {
return _name;
}
};
}
const person = createPerson('太郎');
console.log(person.getName()); // 太郎
Symbolを利用する
- 外部からアクセスしにくい:Symbolはユニークな値であり、外部から意図的にアクセスするのは困難です。
- ユニークなキー
const _nameSymbol = Symbol('name');
class Person {
constructor(name) {
this[_nameSymbol] = name;
}
getName() {
return this[_nameSymbol];
}
}
WeakMapを利用する
- ガベージコレクション:WeakMapはキーがオブジェクトの場合、そのオブジェクトが参照されなくなると自動的に削除されます。
- オブジェクトとの関連付け
const _privateData = new WeakMap();
class Person {
constructor(name) {
_privateData.set(this, { name });
}
getName() {
return _privateData.get(this).name ;
}
}
各方法の比較
方法 | メリット | デメリット | 備考 |
---|---|---|---|
アンダースコア | シンプル | 強制力がない | 非公式な慣習 |
クロージャ | 強力なカプセル化 | コードが冗長になる場合がある | 関数スコープを利用 |
Symbol | ユニークなキー | 外部からアクセスは困難だが、完全に防ぐことはできない | ES6で導入された新しい機能 |
WeakMap | ガベージコレクション | コードがやや複雑になる | オブジェクトとの関連付けに特化 |
ES6のプライベートプロパティとの比較
- 構文が直感的であり、言語レベルでサポートされているため、より自然な形でプライベート変数を扱うことができます。
- ES6のプライベートプロパティは、上記の方法よりも簡潔かつ安全にプライベートな変数を定義できます。
ES6のプライベートプロパティが導入される前は、様々な方法でプライベート変数を表現していました。しかし、ES6のプライベートプロパティは、これらの方法よりも安全かつ簡潔にプライベート変数を定義できるため、現代のJavaScript開発では、ES6のプライベートプロパティが推奨されます。
どの方法を選ぶべきかは、プロジェクトの規模、チームの規約、そして個人の好みによって異なります。ES6のプライベートプロパティが利用できる環境であれば、積極的に活用することをおすすめします。
- TypeScriptなど、JavaScriptのスーパーセットでは、より厳密なプライベート変数のサポートを提供しているものもあります。
- 上記以外にも、プロパティ記述子やProxyを使ってプライベート変数を模倣する方法もありますが、より複雑な実装になります。
javascript class ecmascript-6