ECMAScript2015 (ES6) で機能追加されたもののうち、今回は class
に関連する部分をピックアップしてまとめていきます。
ついに JavaScript でも クラス が使えるようになった!
…のですが、不完全な部分もありますので、この記事を読んでそんなところもピックアップしてもらえればと思います。
ちなみに、ES2015 に関連する まとめ記事 は以下の通りです。
関連記事
- ECMAScript 2015 (ES6) まとめ (基本編)
- ECMAScript 2015 (ES6) まとめ (クラス編) ← この記事
- ECMAScript 2015 (ES6) まとめ (モジュール編)
目次
JavaScript の クラス 概要
Java や C# 等の言語には最初から class
キーワード が存在していますが、 JavaScript には ES2015 まで存在しませんでした。
ES2015 に対応しているブラウザから class
が使えるようになります。
JavaScript において class
を利用する簡単な例を以下に載せます。
// クラスを宣言 class Car { constructor (name) { this.name = name; } drive () { console.log(`drive ${this.name}.`); console.log('zoom zoom ...'); } } // クラスをインスタンス化して利用 var mycar = new Car('ponkotsu'); mycar.drive();
クラスの宣言は class
キーワード に続けて クラス名 を指定することでできます。
クラスの内容は オブジェクト 定義する記載方法と似ていますが、 メンバの区切りにカンマ不要な点が異なります。
クラスを利用する際のインスタンス化は new
で行い、メソッド呼び出しは .
で行うあたりはよくある記法と同じかと思います。
クラス の 定義
クラス宣言
クラス宣言を行うには class
キーワード を利用します。
宣言方法は「classキーワード に引き続き クラス名 を記述する方法」と「変数として クラス定義 する方法」の2通りがあります。
構文
class ClassName { definitions }
var ClassName = class [ClassNameAlias] { definitions }
- ClassName
- クラス名を指定。インスタンス生成時に利用する名前。
- ClassNameAlias
- クラス内部で利用するクラス名。staticメソッドを呼び出すとき等に使う。オプションなので定義しなくても動作する。
- definitions
- クラスの内容を記述。
コンストラクタ
その名の通り、クラスをインスタンス化するとき呼ばれる特別なメソッドです。
名称が決まっており constructor
を利用します。
メソッドになるため仮引数やメソッド本体の記載方法は通常のメソッドと同じです。
JavaScript の クラス ではメンバ変数の初期化をコンストラクタで行います。
構文
var ClassName = class { constructor ([param...]) { statements } }
利用例
var Car = class { constructor (name) { console.log(`create ${name}`); } } var mycar = new Car('ponkotsu'); // "create ponkotsu"
メソッド
オブジェクトの操作を表すメソッドを定義することができます。
通常の関数と同じで関数名と仮引数を定義します。
利用する際はインスタンス化した後に定義したメソッド名を指定することで呼び出せます。
インスタンス化せずに呼び出せる staticメソッド は static
キーワード を用いて定義します。
JavaScript の クラス で通常通りメソッドを追加すると public な扱いになり、どこからでもアクセスできるメソッドになります。
private なメソッドを作りたい場合は ES2015 で追加された Symbol
を使うことで疑似的な表現ができると思います。
Symbol
はユニークな値のため、その名称を知ったうえで意図的に Symbol
を利用してアクセスしない限り メソッド アクセス できません。
構文
publicメソッド
var ClassName = class { MethodName ([params...]) { statements } }
privateメソッド
var ClassName = class { [Symbol('MethodName')] ([params...]) { statements } }
staticメソッド
var ClassName = class { static MethodName ([params...] { statements } }
- MethodName
- メソッド名
- params...
- メソッドに渡す仮引数
- statements
- メソッド本体
利用例
var Car = class { constructor(name) { this.name = name; } // publicメソッド echo () { console.log(this.name); } // privateメソッド [Symbol.for('_echo')]() { console.log(`${(new Date(Date.now())).toISOString()} : ${this.name}`); } // staticメソッド static maintenance() { console.log('now maintenance...'); } }; var o = new Car('hoge'); o.echo(); // "hoge" o._echo(); // TypeError: o._echo is not a function o['_echo'](); // TypeError: o._echo is not a function o[Symbol.for('_echo')](); // "2016-07-01T00:22:36.471Z : hoge" Car.maintenance() // "now maintenance..."
プロパティ
プロパティ(メンバ変数)の定義および初期化は コンストラクタ の中で行います。
プロパティに対するアクセスを setter / getter で制御したい場合は追加で必要な setter / getter を定義を行います。
setter / getter を利用する際は本体となるプロパティは private とするのが通常と思いますので、 Symbol
とセットで定義になるかと思います。
構文
通常の定義
var ClassName = class { constructor () { // publicプロパティ this.publicMember = 'prop1'; // privateプロパティ this[Symbol.for('privateMember')] = 'prop2'; } }
setter / getter を用いた定義
var ClassName = class { constructor () { // プロパティの実態 this[Symbol.for('memberName')] = initialValue; } // getter定義 get PropertyName () { // getterの内容 return this[Symbol.for('memberName')]; } // setter定義 set PropertyName (value) { // setterの内容 this[Symbol.for('memberName')] = value; } }
利用例
var Car = class { constructor(name) { this.name = name; this[Symbol.for('created')] = (new Date(Date.now())).toISOString(); this[Symbol.for('_number')] = Math.floor(Math.random() * 10000); } getCreatedTime() { console.log(this[Symbol.for('created')]); } echo() { console.log(`this name is "${this.name}"`); } get number() { return this[Symbol.for('_number')]; } set number(value) { this[Symbol.for('_number')] = value; } }; var o = new Car('hoge'); o.created; // undefined o.getCreatedTime(); // 2016-07-01T01:00:22.833Z <- インスタンス生成日時 o.echo(); // this instance's name is "hoge" o.number; // 7184 <- 乱数
継承
あらかじめ作成してあるクラスを継承して新しいクラスを作成することができます。
継承は extends
キーワード を利用して親クラスを指定します。
子クラスにおいて親クラスのメソッドを呼ぶ場合、super
キーワードを利用して呼び出します。
親クラスのコンストラクタを呼び出す場合は super()
で呼び出します。
親クラスのメソッドを呼び出す場合は super.parentMethod()
で呼び出します。
子クラスにおいて親クラスのメソッドをオーバーライド(上書き)する場合、同名のメソッドを定義することでオーバーライドできます。
構文
var ChildClassName = class [ChildClassNameAlias] extends ParentClassName { definitions }
- ChilClassName
- 子クラス名
- ParentClassName
- 親クラス名
利用例
// 親クラスの定義 var Car = class { constructor(name) { this.name = name; this.created = (new Date(Date.now())).toISOString(); } getTimeStamp() { return this.created; } drive() { console.log('zoom zoom ...'); } }; // 子クラスの定義 // Car を継承して Lamborghini を作成 var Lamborghini = class extends Car { constructor(name) { // 親コンストラクタを呼び出す例 super(name); } echo() { // 親メソッドを呼び出す console.log('call parent class getTimeStamp() : ' + super.getTimeStamp()); } // オーバーライドの例 drive() { console.log(`fire ${this.name} !!`); } }; var car1 = new Lamborghini('lamgorghini'); car1.getTimeStamp(); // "2016-07-01T04:14:01.131Z" car1.echo(); // call parent class getTimeStamp() : 2016-07-01T04:14:01.131Z car1.drive(); // fire lamgorghini !!
クラス の 利用
インスタンス化
インスタンス化は new
に続いてクラス名を記述することで行えます。
インスタンス化した際は最初に コンストラクタ (constructor
メソッド) が呼ばれます。
ちなみに、インスタンス破棄時に呼ばれる デストラクタ は存在しません。
構文
var instance = new ClassName();
利用例
var User = class User { constructor () { this.id = ''; this.name = ''; } login () { console.log('login'); } logout () { console.log('logout'); } }; var user = new User(); user.login(); user.logout();
ECMAScript2015 (ES2015 / ES6) から利用できるようになった クラス についてまとめてみました。 JavaScript において クラス を利用するとき利用する setter / getter (ES5) や Symbol型 についてもあわせて記載しました。 この記事一本で JavaScript のクラス作成、利用 は出来る…ハズ!
参考記事
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!