JavaScript:prototype(プロトタイプ)で、後からの変更に対応できるコードにしよう

こんにちはタクゾウです。
今回は、JavaSctiptでクラスを使うためのプロトタイプについて復習したいと思います。

プロトタイプとは

JavaScriptにはクラスという概念がないですが、このクラスの代わりになるのがプロトタイプです。
※ES6(ECMAScript2015)ではあるけど、対応ブラウザがまだまだ少ない。
プロトタイプとは、prototyopeプロパティのこと
prototypeに何かを入れておけば、インスタンス化した時に引き継ぐことができます。(オブジェクト指向でいう、staticプロパティやstaticメソッドが作れる。)

コンストラクタだと不便な場合がある!

コンストラクタの書き方では、処理を後から変更したい場合に不便な時があります。
モンスターのコンストラクタからインスタンスを作成するコードを例に説明していきます。

JavaScript
var Monster = function(name, hp, attack){
  this.name = name;
  this.hp = hp;
  this.attack = attack;
  this.doAttack = function(){
    console.log(this.name + 'は' + this.attack + 'のダメージを与えた');
  }
}
var dragon = new Monster('ドラゴン', 9999, 8000);//dragonのインスタンスを作成
var slime = new Monster('スライム', 100, 1);//slimeのインスタンスを作成
console.log(dragon.doAttack());//ドラゴンは8000のダメージを与えた
console.log(slime.doAttack());//スライムは1のダメージを与えた

doAttackメソッドの中の処理を変更したい場合を考えると、
インスタンスにメソッドがコピーされて別々になっているので、それぞれのインスタンスを変更させる必要がる。

JavaScript
dragon.doAttack = function(){
  console.log(this.name + 'は動けなかった');
}
slime.doAttack = function(){
  console.log(this.name + 'は動けなかった');
}

これでは数が多い場合に修正が大変になります、、
これを解決できるのがprototypeです。

prototypeを使った場合

prototypeでメソッド変更に対応できるように記述した例がこちらです。

JavaScript
var Monster = function(name, hp, attack){
  this.name = name;
  this.hp = hp;
  this.attack = attack;
}
Monster.prototype.doAttack = function(){
  console.log(this.name + 'は' + this.attack + 'のダメージを与えた');
}
var dragon = new Monster('ドラゴン', 9999, 8000);
var slime = new Monster('スライム', 100, 1);
console.log(dragon.doAttack());
console.log(slime.doAttack());

コンストラクタとの違いは、コンストラクタを作った後に関数部分は、
prototypeを指定して作成しています。
この記述で先ほど同様にメソッドを変更したい場合は、プロトタイプの記述を変更するだけで
全てのインスタンスのメソッドを変更することができます。

JavaScript
Monster.prototype.doAttack = function(){
  console.log(this.name + 'は動けなかった。');
}
メリット
・修正箇所が少なくてすむ!!
・インスタンスごとにメソッドを増やさないので、メモリの節約になる!!
・インスタンスした後にprototypeを追加してもインスタンスで使用することができる!!

プロトタイプチェーン

プロトタイプチェーンについても簡単に説明します。
prototypeを使ってオブジェクト指向でいう「継承」ができる仕組みのこと
prototypeの中に別のインスタンスをいれておけば、そのインスタンスのプロパティやメソッドが利用できる。
継承元のインスタンスがかわれば、継承先にも反映される。

JavaScript
var Creature = function(){};
Creature.prototype = {
  doAttack : function(){
    console.log(this.name + 'は' + this.attack + 'のダメージを与えた');  
  }
};
var StrongCharacter = function(name, hp, attack, cry){
  this.name = name;
  this.hp = hp;
  this.attack = attack;
  this.doCry = function(){
    console.log(cry);
  }
};
var WeakCharacter = function(name, hp, attack){
  this.name = name;
  this.hp = hp;
  this.attack = attack;
  this.doRun = function(){
    console.log(this.name + 'は全速力で逃げた');
  }
};
StrongCharacter.prototype = new Creature();
WeakCharacter.prototype = new Creature();
var dragon = new StrongCharacter('ドラゴン', 9999, 8000, 'ギャフーン');
var slime = new WeakCharacter('スライム', 100, 1);

dragon.doCry();//ギャフーン
dragon.doAttack();//ドラゴンは8000のダメージを与えた
slime.doAttack();//スライムは1のダメージを与えた
slime.doRun();//スライムは全速力で逃げた

この書き方により、継承元である「Creature」のdoAttack()メソッドが継承先のインスタンスでも使用できるようになります。
もちろん、Creatureの内容を変更すると継承先のインスタンスも変更されます。

まとめ

規模が大きいシステムでは、プロトタイプを使うと便利なので、使えるようにしましょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


Translate »