前回、プロトタイプについて学びましたが、次は prototype を利用した機能実装について学びましょう。
1. オブジェクト指向…難しい
中々、オブジェクト指向といっても概念を理解するのは一苦労です。
しかし、プロトタイプを利用してコーディングをするのは、そこまで複雑ではありません。
これまで3~4つの関数で実装していた機能でも、もしくは そのまま書いている処理でも、考え方をちょっと変えるだけでオブジェクトを利用して構築することが可能です。
まずは、些細な機能でもプロトタイプを利用してクラスとして機能を完結させる書き方にチャレンジしてみましょう。
2. クラスを実装してみる
クラスは、最初に呼び出す時に new 演算子を利用して初期化というものを行います。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/new
new 演算子は以下の処理を行います。
- 空の JavaScript オブジェクトを生成する
- このオブジェクト (のコンストラクター) を他のオブジェクトへリンクする
- ステップ 1 で新しく生成されたオブジェクトを this コンテキストとして渡す
- 関数が自分自身を返さない場合は this を返す
ここまでよくわかりませんね。
実際にためしてみましょう。
例えば、次のような関数を定義してみます。
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; return this; } var p = Person("タカシ","29","男性"); console.dir(p)
実行結果
単純にPersonという関数を定義し、引数を渡し呼び出しただけです。
関数内で利用している this という変数は、JavaScriptで最初から用意されている特別な変数です。
thisに格納されている値は、thisをどこから実行したのか、またはどのような方法で実行したのかで変化します。
thisって何?使い方を覚えて、JavaScriptをもっと楽しく使おう!
https://www.sejuku.net/blog/29389
上記の結果では、Person関数内で呼び出した this は、Window オブジェクトを参照していることがわかります。
では、次に new 演算子を利用してみましょう。
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; return this; } var p = new Person("タカシ","29","男性"); console.dir(p)
本当に new 演算子を Person 関数の前につけただけです。
しかし、実行結果は以下のようになります。
Personというオブジェクトを出力しています。
先ほどの関数として呼び出した結果では this の参照先は window オブジェクトでしたが、new 演算子をつけると this の参照先がその関数内になっていることがわかります。
new 演算子をつけて関数を呼び出した場合、その関数は特別な空間(スコープ)で包まれて、独自のオブジェクトとなります。また、この方法で呼び出したオブジェクトをインスタンスと呼びます。
まだぽかーんとなるかもしれませんが、この this がインスタンス内で共通の値の格納場所になるようなイメージです。
この仕様とprototypeを組み合わせることで、次のような実装が可能となります。
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; return this; } // 名前と歳を文章として加工し返すメソッド Person.prototype.info = function(){ return this.name + "君は" + this.age + "歳です" } var p = new Person("タカシ","29","男性"); var profileText = p.info(); console.log(profileText) // タカシ君は29歳です
実行結果
Person という関数の prototype プロパティ内に、info というメソッドを定義します。
名前と歳を文章として加工し返すメソッドです。
この時、実行結果から Person.prototype.info 内で呼び出している this.name、this.age も、同じPerson内で処理された値を参照していることがわかります。
プロトタイプは継承され、生成されたオブジェクト(この場合はインスタンス)でも、利用することができます。
一見関数にはみえるのですが、new 演算子で初期化し利用することを前提としたものをJavaScriptではクラスと呼びます。
コンストラクタについて
new Person()を実行した時には、最初に定義した Person 関数が呼び出されます。
この最初に呼び出される関数をコンストラクタと呼びます。
コンストラクタ(英:constructor)とはオブジェクト指向のプログラミング言語で登場する用語のひとつでありインスタンスを作成したタイミングで実行されるメソッドのことです。
もう少しざっくり書くとクラスをnewした瞬間に実行される関数のことです。
インスタンスを生成する時に、thisは初期化される
new 演算子でインスタンスを生成すると、this は初期化されます。
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; return this; } // 名前と歳を文章として加工し返すメソッド Person.prototype.info = function(){ return this.name + "君は" + this.age + "歳です" } var takashi = new Person("タカシ","29","男性"); var takashi_info = takashi.info(); console.log(takashi_info) // タカシ君は29歳です var shogo = new Person("しょうご","28","男性"); var shogo_info = shogo.info(); console.log(shogo_info) // しょうご君は28歳です
初期化されるということは、与える引数を変えて何度も生成することが可能です。
メンバ変数 (インスタンス変数)
上の例で出てきているように、クラスの内部でメンバ変数を定義・参照するには this.<プロパティ名> を使います。インスタンス変数やメソッド呼び出しの際にJavaScript では this が必ず必要です。
まとめ
- new 演算子を関数を呼び出す前につけることで、その関数内で呼び出すことができる this の参照先がその関数自身になる
- new 演算子で呼び出し最初に実行される関数をコンストラクタと呼ぶ
- new 演算子で生成したオブジェクトをインスタンスと呼ぶ
- プロトタイプは継承され、生成されたオブジェクト(この場合はインスタンス)でも、利用することができる。
Udemyを実際に体験した方の感想記事もぜひご覧ください♪