※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。
ES2015でクラスを表現するためのclass構文が導入されました。
ES2015より前はこれらのクラスをclass構文ではなく、関数で表現していました。 その表現方法は人によってさまざまで、これもclass構文という統一した記法が導入された理由の1つだそうです。
###クラスの定義方法
//クラス宣誓文による方法
class クラス {
constructor() {
}
}
//クラス式による方法
const クラス = class {
constructor() {
}
};
###コンストラクタによる初期化方法
//クラス式に要る方法
class クラス {
constructor(name) {
this.name = name;
}
}
コンストラクタ関数内のthisは、インスタンス自体を参照。
よって、インスタンスのプロパティーを初期設定できる。
詳細はこちらの記事をご覧ください。
【JavaScript】JavaScriptの 「this」とは
###インスタンス作成方法
const インスタンス = new クラス("Taro");
作成したインスタンスは、それぞれ別のオブジェクトである。
const myClass1 = new MyClass("Taro");
const myClass2 = new MyClass("Taro");
console.log(myClass1 === myClass2); // => false
###クラスのプロトタイプメソッドの定義
class クラス {
メソッド() {
}
}
const インスタンス = new クラス();
インスタンス.メソッド();//メソッド内のthisはインスタンス。
メドッド内で定義した、thisは呼び出し元を参照する。つまりインスタンスオブジェクトを参照します。
詳細はこちらの記事をご覧ください。
【JavaScript】JavaScriptの 「this」とは
この様に、クラス内で定義したメソッドはプロトタイプメソッドとなるため、作成されたインスタンスから共有されることになる。(インスタンスメソッドとも言う)
詳細はこちらの記事をご覧ください。
【JavaScript】プロトタイプオブジェクトについて1
class MyClass {
constructor() {
}
say() {
console.log('hey');
}
}
const myClass1 = new MyClass();
const myClass2 = new MyClass();
// 各インスタンスオブジェクトのメソッドは同じ関数を参照している。
console.log(myClass1.say=== myClass2.say); // => true
##クラスのインスタンスに対してメソッドを定義する
一方、個別のインスタンスに対し、メソッドを定義することもできます。インスタンスのプロパティーに対し、値を設定する場合と同じ方法です。
class クラス {
constructor() {
this.say = ()=>{
console.log("hello");
}
}
thisはインスタンス自体を参照するので、インスタンスのsayプロパティにメソッドを与えます。
プロトタイプメソッドと、異なりそれぞれのインスタンスにけるsayメソッドは、異なるオブジェクトを参照してます。
一つのクラスで同名のプロトタイプメソッドとインスタンスメソッドを作成した場合、インスタンスメソッドが優先して呼ばれすます。また、この時、後から作った方が、前からあったメソッドを上書きするわけではありません。あくまで、プロトタイプメソッドはプロトタイプオブジェクトに定義され、インスタンスオブジェクトはインスタンスメソッドに定義されています。
プロトタイプオブジェクトはこちらを参照ください。
【JavaScript】プロトタイプオブジェクトについて1
##プロトタイプチェーンについて
なぜ、インスタンスが、クラスのプロトタイプメソッドを呼び出すことができるかというと、プロトタイプチェーンという仕組みによります。
プロトタイプチェーンは2つの処理からなります。
####(1)インスタンス作成時に、インスタンスのプロトタイプロパティーに、クラスのプロトタイプオブジェクトへの参照を保存する処理。
今下記のような、プロトタイププロパティーに、sayというメソッドが定義されたプロトタイプオブジェクトを持つHumanクラスがあるとする。この、プロトタイプオブジェクトは、パソコン上のメモリ6と言う空間に格納されているとする。
あくまでイメージです。
//Humanクラス
Human = {
prototype : { //メモリ6に格納。
say(){
console.log("hello");
}
}
}
このHumanクラスから、インスタンスを作成する。
const human = new Human();
この時インスタンスは下記のようなプロトタイプメソッドを持ちます(イメージ)
human = {
prototype:{ //インスタンスhumanのプロトタイプオブジェクト
prototype : メモリ6を参照 //クラスのプロトタイプオブジェクトの参照情報を持つ。
}
}
####(2)インスタンスからプロパティー(またはメソッド)を参照する時に、プロトタイププロパティを連鎖して探索する処理。
今、下記のようにインスタンスからメソッドを呼び出したとする。
human.say();
//hello
この処理の流れを見ていくと、まず最初に、humanインスタンスのsayと言うな名前のメソッドをプログラムは探しに行く。
ここでは、メソッドとして定義して定義されていないので、次にインスタンス自身のプロトタイプオブジェクトを探しにいく。
イメージ
human.prototype.say();
しかし、ここでも定義されていないので、さらに深いプロトタイプオブジェクトを探索しにいく。
イメージ
human.prototype.prototype.say();
このプロトタイププロパティーはクラスのプロトタイプオブジェクトの参照情報を保持しているので、クラスのプロと対オプオブジェクトに定義されているsay()メソッドを参照することができる。
上記2つの仕組み(プロトタイプチェーン)により、クラスのメソッドがインスタンスに引き継がれるのです。
また、最終的にメソッドが呼ばれる際は
say.call(human);
の様に、thisの参照先をhumanにするために、callメソッドで呼ばれるイメージです。
続きはこちら
【JavaScript】クラス構文について 2 〜継承〜