2013年7月16日火曜日

JavaScriptの言語仕様の理解



◆ 目的
JavaScriptでコンストラクタを用意し、そこからオブジェクト(インスタンス)を作り、プロトタイプチェーンをたどる様子を模式図を使って理解する。

少々厄介なオブジェクト、プロトタイプの関連が目が覚めたように分かるはずである。



◆ サンプルコード
・Personコンストラクタ関数Person()の作成

コンストラクタ関数は共通の性質はふるまいをもったオブジェクトを作る型である。
他の言語で言うところのクラスのようなものは、JavaScriptではただの関数で定義できるということである。

new演算子とともに記述されることを想定してカスタムコンストラクタ関数を生成する際には、通常の関数との混同を避けるために関数の最初の文字を大文字にするのがよいだろう。

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

this.gender = gender;

this.getAge = function() {
return this.age;
};

this.getGender = function() {
return this.gender;
};
};


・プロトタイププロパティに新しいオブジェクトの設定
Person.prototype.birthday = 'yyyymmdd';


・オブジェクト(インスタンス)化
person = new Person(20, 'man') 


コンストラクタ関数と言ってもただの関数のようなものなのだが、new演算子を使って呼ばれた場合にただの関数とは異にする特徴を示す。コンストラクタ関数はreturnがなくともよい。オブジェクトインスタンスを構築して返す。

JavaScriptではパラーメタに引数を渡さなくてもかまわない。引数が渡されなければその変数はUndefinedが設定される。



◆ 模式図
・サンプルコードの模式化
                       
Function.prototype   Object.prototypeへ
        ↑                  ↑
プロトタイプチェーン(__proto__ 経由)

Person()             Person.prototype
+---------------+    +----------------------+
| __proto__     |    | __proto__            |
| prototype     |    | constructor          |
| age           |    | birthday: 'yyyymmdd' |
| gender        |    |                      |
| getAge        |    |                      |
| getGender     |    |                      |
+---------------+    +----------------------+

 インスタンス化               ↑
      ↓              プロトタイプチェーン

     person
      +----------------------+
      | __proto__ *         |
      | age: 20              |
      | gender : 'man'       |
      | getAge: -            |
      | getGender: -         |
      +----------------------+

*
自分自身に存在しないプロパティ・メソッドが呼び出されると、__proto__ ([[Prototype]])をめぐった先を参照する。
person.__proto__ === Person.prototype

つまり、参照である。では、prototypeプロパティとしてbirthdayを設定したが、これはクラス変数のように、newされたオブジェクトで共有されるのだろうか。
person1 = new Person(〜);
person2 = new Person(〜);

person1.birthday = 19910101
person2.birthday = 20010101

alert(person1.birthday) // ?

答えは共有されない。person1.birthdayは19910101と表示される。代入時には、person1にbirthdayというプロパティが新たに作られ、そこに設定が代入されるためである。


(参考)
https://www.matthieuveillon.com/class/