技術はあとからついてくる。

技術はあとからついてくる。

就活開始の半年前にエンジニアに目覚めた人

JavaScriptのプロトタイプとプロトタイプチェーン

プロトタイプとは

  • クラスのようなもの
  • JacaScriptには「クラス」という概念がない
  • (ES6ではクラスの概念ができたが普及は微妙)

prototypeプロパティ

  • オブジェクトには、メンバを追加するためのprototypeプロパティが用意されている
  • 意識して使わない限りは空のオブジェクトを参照している
  • 何かを格納すると、オブジェクトをインスタンス化した先のオブジェクトに引き継ぐことができる
var Phone = function(name) {
    this.name = name;
};
Phone.prototype.getName = function() {
    retrun this.name
};
var featurePhone = new Phone('feature phone');
var smartPhone = new Phone('smart phone');

console.log(featurePhone.getName()); // feature phone
console.log(smartPhone.getName()); // smart phone

prototypeプロパティを使って、オブジェクトにメソットを追加する例 プロパティに格納したメソッドが、インスタンス化したそれぞれのオブジェクトに引き継がれている。

なぜわざわざプロパティを使ってメソッドを定義するのか? コンストラクタの中に定義すれば良いのでは?

→ メモリ使用量の削減のため

  • インスタンス化したオブジェクトは、コンストラクタで定義されているメンバ分のメモリ領域を都度確保する。
  • メソッドはインスタンスを通して全て同じ振る舞いをするため、個別にメモリを確保するのは無駄

prototypeプロパティがあれば * インスタンス化されたオブジェクトは、使用したコンストラクタのprototypeプロパティに対して暗黙の参照を持つ。 * prototypeプロパティに格納したメソッドにも暗黙の参照を持っているので、自前でメソッドを持つ必要がない。

これにより、無駄なメモリ消費が避けられる

もう一つのメリット

var Phone = function(name) {
    this.name = name;
};

var featurePhone = new Phone('feature phone');

Phone.prototype.getName = function() {
    return this.name;
};

var smartPhone = new Phone('smart phone');

console.log(featurePhone.getName()); // feature phone
console.log(smartPhone.getName()); // smart phone

featurePhoneの生成を、prototypeプロパティにメソッドを追加する前に移動しても featurePhoneもgetNameメソッドを呼び出せている。 prototypeプロパティでメソッドおを管理すれば、インスタンスがオブジェクト(コンストラクタ)の変更をリアルタイムに認識できる

ここまでまとめ

  • コンストラクタを定義する際には、メソッドは必ずprototypeプロパティで管理する

プロトタイプチェーン

JavaScriptオブジェクト指向の継承を行うための仕組み

var Phone = function() {};
Phone.prototype = {
    getOwner: function() {
        console.log('Owner is', this.owner);
    }
};

var SmartPhone function(owner) {
    this.owner = owner
};
SmartPhone.prototype = new Phone(); // ①
SmartPhone.prototype.tap = function() {
    console.log('tap!');
};

var myPhone = new SmartPhone('hatenai');
myPhone.getOwner(); // ② Owner is hatena
myPhone.tap(); tap!

var otherPhone = new SmartPhone('blog');
otherPhone.getOwner(); // Owner is blog
otherPhone.tap(); // tap!

①がプロトタイプチェーン

継承したオブジェクトのインスタンスを、自身のprototypepプロパティに格納する

②におけるメンバ解決

  • myPhoneオブジェクト自身のgetOwnerメソッドを探す
  • 見つからないため、myPhoneのコンストラクタ(SmartPhoneオブジェクト)のプロトタイプ(Phoneオブジェクトのインスタンス)にgetOwnerメソッドを探しに行く
  • PhoneオブジェクトのプロトタイプにてgetOwnerメソッドを発見する

まとめ

  • プロトタイプチェーンが使いこなせれば、オブジェクト指向ライクな記述ができるようになる。