JavaScript

メソッドを作る

はじめに

newで独自オブジェクトを作るで、オブジェクトを作る方法を示しましたが、ここにメソッドを追加します。

メソッドは prototype に入れる

ソース

isYakusodhi()というメソッドを作ってみました。

最初に、全体を示します。

/*
 * Person 人のデータ
 * @param name 氏名
 * @param age 年齢
 */
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.isYakudoshi = function() {
  if( this.age == 25 || this.age == 42 || this.age == 61 ) {
    return "厄年です";
  }
  else {
    return "違います";
  }
}

Person.prototype.CLASSNAME = 'Person';

var p1 = new Person("山田太郎", 30);
var p2 = new Person("中村太郎", 42);

console.log(p1.name+" は厄年?: "+p1.isYakudoshi()); // 山田さんは厄年でない
console.log(p2.name+" は厄年?: "+p2.isYakudoshi()); // 中村さんは厄年

console.log(p1.CLASSNAME);

次にメソッドだけを切り出してみます。

Person.prototype.isYakudoshi = function() {
  return this.age == 25 || this.age == 42 || this.age == 61;
}

new Person()で作られたオブジェクトは2つ(別に3つ以上であっても変わりません)であるのに対して、メソッドは1つ作っているだけです。

Person.prototypeの下に置いておいたものは、new Person()で作られたオブジェクトの全てからアクセス可能です。

これによっていくつものオブジェクト同士で共有できています。同じ関数を呼び出し使うので、new Personで生成するたびに関数を作る必要が無くなります。

ひとたびメソッドを作れば使いまわせるところが、メソッドの良いところです。

メソッドにアクセスする手順

もう少しアクセスする手順を掘ってみます。処理系がメソッドp1.isYakudoshiにアクセスする手順は、次の通りです。

  • p1isYakudoshiが存在しているならそれを実行
  • なければp1.__proto__isYakudoshiが存在しているならそれを実行
  • それでもなければp1.__proto__.__proto__を見て存在しているならそれを実行(以下繰り返し)

ここで__proto__というキーが出てきています。newで独自オブジェクトを作るで少しだけ言及していますが、「「生成したオブジェクト」の__proto__に関数のprototypeを代入」しています。オブジェクトには必ず存在します。

具体例を見てみましょう。p1は次のようになっています。

{
  "name": "山田太郎",
  "age": 30,
  "__proto__": { // Person.prototypeと同じ
    "isYakudoshi": function() {...}, // Person.prototype.isYakudoshiと同じ
    "__proto__": {
      ...
    }
  }
}

p1.isYakudoshiは存在しません(p1にあるのはname, age, __proto__)。
次にp1.__proto__を見ます。ここにisYakudoshiがあるので、これを実行します。

thisが参照するもの

次にメソッド内部を見てみると、thisというワードが出ています。

newで独自オブジェクトを作るでコンストラクタを呼び出す際にthisが「生成されたオブジェクト」を参照するように設定されている、と言いました。

今回の場合もthisは、オブジェクトを参照します。

p1.isYakudoshiでは、thisp1は同じオブジェクトを参照しています。ですから、メソッド内でthisのメンバの値を変えると、p1のメンバの値が変わります。

prototypeに入れられるのはメソッド(関数)だけではない

Person.prototype.CLASSNAME = 'Person';

という式文があります。これによって、p1でもp2でも同じ値"Person"になります。

おわりに

(関数).prototypeによって newで生成したオブジェクト間でメンバが共有されることと、メンバを関数にすると、共有した関数を呼び出せるので、メソッドのようになることを紹介しました。