ちょっと一息

ちょっと一息

主に自分の学んだこと、使えそうなことをまとめてます

JavaScriptのオブジェクト(プロトタイプ) ~ その2 ~

前回の続き

あっという間に今年も残すところあと1日ですね。
少し間が空きましたが、前回の続きでJavascriptオブジェクト指向についてです。
前回クラスの定義コンストラクについてまとめました。今回はプロトタイプを使ったメソッドの宣言や継承をまとめてみました。

メソッドの宣言

メソッドを後付けする

Personオブジェクトにメソッドを後付けしてみる。

var Person = function(name, age) {
 this.name = name;
 this.age = age;
};

var taro = new Person('太郎', 20);

taro.greet = function() {
 return "名前: " + this.name + ", 年齢: " + this.age;
}

console.log(taro.greet());    // 名前: 太郎, 年齢: 20

このようにして、メソッドを後から追加することができる。
ここで、もう一つPersonオブジェクトのインスタンスを作成すると、

var hanako = new Person('花子', 25);
console.log(hanako.greet());    // Uncaught TypeError

となり最後がエラーになりなる。
メソッドを後付けすると、インスタンス固有のメソッドとなってしまうみたい。
同じクラスから生成してもそれぞれのインスタンスが持つものが違ってしまう。

prototypeを使う

後付けすると、インスタンスが持つプロパティやメソッドが異なることがわかった。
インスタンスで共通のものを定義する場合はコンストラクタで前回定義したけど、これは無駄にメモリを消費するらしい。
メモリ消費を抑えるためにprototypeというプロパティを使ってメンバを追加する。

var Person = function(name, age) {
 this.name = name;
 this.age = age;
};

// getName, getAgeを追加

Person.prototype = {
 getName : function() { return this.name; },
 getAge : function() { return this.age; }
};

var suzuki = new Person('鈴木', 30);

console.log(suzuki.getName());    // 鈴木

こうすることで、メモリ消費を抑えたメンバの追加ができるみたい。

メンバが呼び出された時の動作は、

  1. インスタンスにメンバがあるかどうか確認
  2. インスタンスにメンバがない場合は、元となるPersonオブジェクトを暗黙的に参照してメンバを取得

といった感じになる。
インスタンスメソッドを定義するときはprototypeプロパティを使えば良さそう。

静的メンバを定義するときは、

Person.Tribe = 'ヒト族';

静的メンバはオブジェクト(クラス)で共通のものだから、このようにオブジェクトに直接追加でいい。

継承

次に、元のオブジェクトを引き継いで新しいクラスを作成する場合

プロトタイプチェーン

プロトタイプの連なりのこと。
プロトタイプにインスタンスを設定すると暗黙的に参照できるようになり、継承ができるようになる。
例えば、Personオブジェクトを継承したKansaizinオブジェクトを作ってみると

var Person = function() {}

Person.prototype = {
 hello : function() { return 'おはよう'; }
};

var Kansaizin = function() {};
Kansaizin.prototype = new Person();

Kansaizin.prototype.say = function() { return 'なんでやねん!'; }

// おっちゃん
var ottyan = new Kansaizin();

console.log(ottyan.hello());    // おはよう
console.log(ottyan.say());    // なんでやねん!

こんな感じに、Personオブジェクトのhelloメソッドを呼び出すことができてる。
helloを呼び出した時の動作は、

  1. Kansaizinオブジェクトのottyanインスタンスのメンバを探して
  2. helloメンバがないのでKansaizinオブジェクトのプロトタイプPersonのインスタンスのメンバを探して呼び出す。

メンバをプロトタイプを次々辿って呼び出すのでプロトタイプチェーンと呼ばれているみたい。

継承したメソッドのオーバーライド

継承した親オブジェクトのメソッドを子オブジェクトで変更したい場合は、

Kansaizin.prototype.hello = function() { return 'おはようさん!'; }

console.log(ottyan.hello());    // おはようさん!

prototype.helloとして書き換えればオーバーライドができる。

まとめ

今回は、prototypeプロパティを使ったメソッドの宣言、継承をまとめました。暗黙的な参照っていうのが分かりにくいけどメモリ消費を抑えれるのはいいね!
より詳細は、またまとめようと思うけど、ES6ではclass構文が使えるので、先にこっちでの書き方とかをまとめてみよう!
次は、最近firebaseとかGoに触れたのでまたまとめてみます。

みなさん今年も1年お疲れ様でした。良いお年をお迎えください!