ES6(ES2015) から、JavaScript でも C++, PHP, Python などの言語と似た class 定義が可能となりました。class でクラスを定義し、new
でクラスのインスタンス(オブジェクト)を生成します。delete はオブジェクトを削除します。下記の例では、Animal という名前のクラスを定義し、Animal オブジェクトを生成・削除しています。
class Animal { } var o1 = new Animal(); delete o1;
constructor() は、オブジェクトを生成する際に初期化関数として呼ばれるメソッドを定義します。下記の例では、オブジェクト生成時に種別(type)引数を渡し、オブジェクト内部のメンバ変数(this.type)に記録しています。
class Animal { constructor(type) { this.type = type; } } var o1 = new Animal("Cat"); console.log(o1.type); // Cat
クラス定義の中では、メソッドを定義することができます。メンバ関数は、オブジェクト.メンバ関数名() の形式で呼び出します。メソッドを定義する際は、function は不要です。
class Animal { setType(type) { this.type = type; } getType() { return this.type; } } var o1 = new Animal(); o1.setType("Cat"); console.log(o1.getType()); // Cat
static は、スタティックメソッドを定義します。スタティック関数は、オブジェクトを生成しなくても、クラス名.スタティック関数名() で呼び出すことができるメソッドです。
class Animal { static hello() { console.log("Hello!"); } } Animal.hello(); // Hello!
get はゲッター(getter)、set はセッター(setter)を定義します。ゲッター・セッターは、クラス利用者に対してはプロパティ(属性)のように簡単に代入や参照ができ、かつ、クラス開発者にとっては、代入・参照の際にメソッドがコールされ、代入・参照時にログを記録したり複雑な内部処理を実行することが可能となります。
class Animal { get type() { console.log("get:" + this._type); return this._type; } set type(arg) { console.log("set:" + arg); this._type = arg; } } var o1 = new Animal(); o1.type = "Cat"; // getter メソッドが呼ばれる console.log(o1.type); // setter メソッドが呼ばれる
prototype を用いて、定義済のクラスに変数やメソッドを追加することができます。
class Animal { } Animal.prototype.type = "Unknown"; Animal.prototype.hello = function() { console.log("Hello!"); } var o1 = new Animal(); console.log(o1.type); o1.hello();
クラスは継承することができます。継承元をスーパークラス(親クラス)、継承先をサブクラス(子クラス)と呼びます。Animal クラスを親クラスとして、Cat という子クラスを定義するには extends を用いて次のようにします。子クラスでは、親クラスのメソッドや変数を継承することができます。
class Animal { hello1() { console.log("Hello!"); } } class Cat extends Animal { hello2() { console.log("Hello Hello!"); } } var o1 = new Cat(); o1.hello1(); // Hello! o1.hello2(); // Hello Hello!
super() は親のコンストラクタを呼び出します。super() は最初に使用する this よりも先に呼び出す必要があります。
class Animal { constructor(type) { this.type = type; } } class Cat extends Animal { constructor(name) { super("Cat"); this.name = name; } } var o1 = new Cat("Mii-chan"); console.log(o1.type); // Cat console.log(o1.name); // Mii-chan
子クラスのコンストラクタを省略すると、子クラス作成時の引数を使用して親クラスのコンストラクタが自動的に呼び出されます。これは、constructor(...args) { super(...args); } と同じ動作となります。
class Animal { constructor(name) { this.name = name; } } class Cat extends Animal { // constructor(...args) { super(...args); } } var o1 = new Cat("Mii-chan"); console.log(o1.name); // Mii-chan
下記の様にして、親クラスのメソッドを呼び出すこともできます。
class Animal { hello() { console.log("Hello!"); } } class Cat extends Animal { hello() { super.hello(); } } var o1 = new Cat(); o1.hello(); // Hello!
下記の様にクラス式を用いて、クラス名を持たない匿名クラスを作成することができます。
var o1 = class { constructor() { this.type = "Cat"; } }; console.log(o1.type); // Cat