前回はこちら
プロトタイプベースのjavascript設計 (1)
http://rei19.hatenablog.com/entry/2013/05/21/005713
コンストラクタを作ってnewを使うとprototypeを引き継いだオブジェクトを作るよ!というところまで書きました。
今回はjavascriptにおける継承の概念について書いてみます。
とりあえずポピュラーな形はこんな感じ。
var App = App || {}; App.Base = (function(){ // コンストラクタ function Base(){} // 初期化処理 Base.prototype.Initialize = function(){ // 引数をプロパティにせっと this.name = arguments[0]; this.id = arguments[1]; } // 確認用 Base.prototype.showProperty =function(){ console.log(this.name); console.log(this.id); } return Base })(); App.Hoge = (function(){ // コンストラクタ function Hoge(){ this.Initialize.apply(this, arguments); } // プロトタイプ継承 Hoge.prototype = new App.Base; // メソッド定義 Hoge.prototype.tekitou = function(){ // ロジック return 'Hogeだお'; } return Hoge; })();
本筋の話ではないですが、javascriptの開発をしていると必ず出てくる問題はグローバル空間の汚染で、ある程度の規模の開発であれば気を使うべきでしょう。
そんな訳で、サンプルコードではAppにコンストラクタを追加していくという構造にしています。
んでは、継承の話に戻って上からコードを解説します。
まずはBaseというコンストラクタを作って、InitializeとshowPropertyというメソッドを追加しています。
これが継承元のプロトタイプとなります。
ちなみにコンストラクタを作る際、無名関数の即時実行とクロージャを使ってグローバル空間の汚染を防いでいます。
使わないで書くとこんな感じ。
var App = App || {}; // 書き方① function Base(){ this.Initialize = function(){ // 引数をプロパティにせっと this.name = arguments[0]; this.id = arguments[1]; } this.showProperty = function(){ console.log(this.name); console.log(this.id); } } App.Base = Base; // 書き方② function Base(){} Base.prototype.Initialize = function(){ // 引数をプロパティにせっと this.name = arguments[0]; this.id = arguments[1]; } Base.prototype.showProperty =function(){ console.log(this.name); console.log(this.id); } App.Base = Base;
どちらもBaseという名前がグロ−バル空間に残ってしまうという問題があります。
①と②の違いはprototypeを使っているか使っていないかの違いですね。
①はnew でオブジェクトが作られる度にInitializeとshowPropertyの関数が生成されるのでメモリ的によろしくありません。
②の書き方であればBaseのprototypeを見るのでnewしたときによけいなメモリを使いません。
※なんのこっちゃと思う人はプロトタイプチェーンでぐぐるといいっす。
で、その次にHogeというコンストラクタを作っています。
注目するのはまず、Hogeのコンストラクタの定義後のコード
function Hoge(){ this.Initialize.apply(this, arguments); } // プロトタイプ継承 Hoge.prototype = new App.Base; // メソッド定義 Hoge.prototype.tekitou = function(){ // ロジック return 'Hogeだお'; }
HogeのプロトタイプにBaseのオブジェクトをセットしています。
継承先のプロトタイプに継承させたいオブジェクトをセットする。これがjavascriptの継承です。
コンストラクタの中身を見るとこんな感じ
Hogeのprototypeは何もしなければHogeになりますがBaseを継承しているのでBaseになっています
次にHogeのコンストラクタ内を見てください。Baseで定義したInitializeをコールしています。
newを使ってHogeのオブジェクトを作るとBaseで定義したInitializeが呼ばれてプロパティに値がセットされるという流れになります。
もちろん作ったHogeオブジェクトからはBaseのshowPropertyメソッドも問題なく呼べます。
以上がスタンダードなjavascriptの継承の話でした。
webサービスでリッチコンテンツが増え、クライアント側でのMVCアーキテクチャの整理なんかをするタイミングが来たら、この辺の話は抑えておくと綺麗な設計が出来るかなと思いますた。