feeds2012/03/05カテゴリー:JavaScriptJavaScriptでのprototypeを利用したクラスの継承TweetJavaScriptは、プロトタイプベースのオブジェクト指向言語であるため、クラスベースのプログラミング言語で使われるextendsのようなクラスを継承するための特別な構文はありませんが、prototypeを利用することにより、継承の機能を実現することができます。下記の例では、スーパークラスAnimalを継承したサブクラスDogを定義しています。サブクラスのコンストラクタ内でcallメソッドを使ってスーパークラスのコンストラクタを呼び出します。次にサブクラスのprototypeにスーパークラスのインスタンスを代入します。これで、サブクラスからスーパークラスのプロパティやメソッドにアクセスできるようになりますが、このままではコンストラクタ内のthisがスーパークラスを指してしまうので、サブクラスのprototype.constructorにサブクラスのコンストラクタを渡します。これで、機能的には問題なく継承できているように見えますが、出力結果を見るとスーパークラスのコンストラクタが2回実行されていることが確認できます。これは、サブクラスのprototypeにスーパークラスのインスタンスを代入する際に呼んでいるコンストラクタが原因です。constructorDogcrytruetrue*/ダミークラスを利用した継承時のコンストラクタ重複問題の解決クラスの継承時にコンストラクタが2回呼ばれてしまう問題の解決策として、まずダミークラスを使った方法を試してみます。下記の例では、ダミーのクラスを用意し、ダミークラスのprototypeにスーパークラスのprototypeを代入しておき、サブクラスのprototypeにはダミークラスのインスタンスを渡しています。出力結果を見るとスーパークラスのコンストラクタは1回しか呼ばれず、且つ継承の機能を実現できていることが確認できます。次にObject.createを利用して、継承時のコンストラクタ重複問題を解決してみます。下記の例では、Object.create()でスーパークラスのprototypeをサブクラスのprototypeに代入しています。出力を見るとダミークラスを使った場合と同様にスーパークラスのコンストラクタは1回しか呼ばれず、且つ継承の機能を実現できていることが確認できます。IE8以下のようなObject.createが使えない古いブラウザでは、自前でObject.createを定義するようにしています。constructorDogcrytruetrue*/メソッドのオーバーライドJavaScriptでは、オーバーライドのための特別な構文はありませんが、サブクラスでスーパークラスのメソッドと同じ名前のメソッドを定義するとオーバーライドすることができます。下記の例では、サブクラスでスーパークラスのメソッドをオーバーライドしていますが、実行してみるとサブクラスに定義したメソッドが実行されていることが確認できます。出力:bowwowプロトタイプチェーンJavaScriptでは、インスタンスのプロパティ(メソッドを含む)が参照された際、まずインスタンス自身のプロパティを探し、見つからなければprototypeプロパティを探します。それでも見つからなければ、prototypeのprototypeプロパティといった具合に最上位のObjectオブジェクトまで連鎖的に探し続けます。このprototypeを連鎖的に辿る継承のメカニズムをプロトタイプチェーンといいます。下記の例では、Animalクラスを継承したDogクラスを定義し、さらにDogクラスを継承したPoodleクラスを定義して、それぞれのクラスのprototypeに同じ名前のメソッドを定義しています。小クラスから順にprototypeに定義したメソッドをdeleteで削除していますが、削除後にメソッドを実行すると親クラスのメソッドが実行されていることがわかります。エラースーパークラスのprototypeの動的拡張プロトタイプベースの特徴として、prototypeを動的に拡張できる点が挙げられます。下記の例では、サブクラスDogをインスタンス化した後でスーパークラスAnimalにメソッドを追加していますが、Dogクラスのインスタンスからも追加したメソッドを実行できることが確認できます。