ES6 における JavaScript のクラス定義
JavaScript はプロトタイプベースの言語であり、Java, C++, Python などのクラスベースの言語とは異なりクラスというものが存在しませんでした。しかしクラスベースのオブジェクト指向の書き方は人間に理解しやすくプログラムが書きやすく、何より他の人気のある言語の経験者にとって分かりやすいので、プロトタイプを使ってクラスと同等なことを実現するということが JavaScript でも行われていました。 そして、ついに 2015 年 6 月に標準仕様が発行されたECMAScript 6(ES6)で JavaScript にも「クラス」の文法が追加されました。 プロトタイプベースの JavaScript でクラスに相当することは割りと簡単に実現できるので、そういう意味ではプロトタイプベースはより柔軟でクラスベースよりも表現力に優れていたのかもしれませんが、結局はほとんどの場合においてはクラスベースの考え方の方が人間に理解しやすく利用しやすかった...といったところでしょうか。
実行環境
2015 年 10 月現在サポートが進んでいる最中で最新のブラウザでも完全にはサポートされていません。
- Firefox は nightly builds でのみ有効になっている
- Chrome では 43 から class がサポートされている。ただしstrict modeでないと class が利用できません。 class の内部が strict mode になるという仕様とは書いてあるけれど、 class 自体は strict mode でなくても本来は使えるはず?
- (iOS) Safari は Safari9 からサポートされている。strict mode なしで使える。
クラスとコンストラクタの定義
ES6 ではclass
キーワードを使ってクラスを定義します。class
のブロックの中でconstructor
という名前の関数を定義するとそれがコンストラクタとして利用されます。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
クラスのインスタンスの生成とコンストラクタの呼び出しには new 演算子を使います。
var alice = new Person("Alice", 7);
ちなみにnew
は ES6 以前から JavaScript に存在する機能です。new
の JavaScript 本来の仕様と使い方についてはES6 以前の JavaScript におけるクラスの実現方法を参考にしてください
メンバ変数 (インスタンス変数)
上の例で出てきているように、クラスの内部でメンバ変数を定義・参照するにはthis.<プロパティ名>
を使います。JavaScript では Java や C++ と違いthis を省略することは不可能なので注意してください。Python を知っている人はthis
はself
に相当するものだと思うと分かりやすいかと思います。インスタンス変数やメソッド呼び出しの際に Python ではself
を付けなければならないように JavaScript ではthis
が必ず必要です。
メソッド定義と呼び出し
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log("Hello, I'm " + this.getName());
}
getName() {
return this.name;
}
}
ES6 では class ブロックの中にconstructor
以外の名前の関数を定義するとメソッドになります。
またメソッド内から他のメソッドの呼び出しを行う場合はthis.<メソッド名>(引数)
を使います。
メンバ変数の場合と同様に、メソッド呼び出しの際にthis を省略することは不可能なので気をつけて下さい.
private, protected
JavaScript でクラスを実現する場合、メンバ変数やメソッドを private
や
protected
にすることはできません。 ただし名前規約で private
なものを名前でわかりやすくして間違えてアクセスしないようにすることはできます。
Google の JavaScript
のスタイルガイド
では private なメソッド, メンバ変数は名前の末尾に _
をつけることが求められています。
継承
クラスの継承は ES6 では以下のように行います。
class Child extends Parent {
constructor(a, b) {
// 親クラスのコンストラクタ呼び出し
super(a);
// ...
}
// オーバーライド
doSomething() {
// 親クラスのメソッド呼び出し
super.doSomething();
// ...
}
}
- ES6 JavaScript でクラスを継承するには
extends
を使います。class Child extends Parent {...}
- 小クラスのコンストラクタの中で親クラスのコンストラクタを呼び出すには
super(...)
を使います。 - 子クラスで親クラスと同名のメソッドを定義すればメソッドがオーバーライドされます。
子クラスから親クラスのメソッドを呼び出すには
super.methodName(...)
のようにします。