おれの技術日記

元はJava+SQLがメインのエンジニア、フロントエンドは軽くかじった程度で苦手。最近忘れっぽいので覚えたことをいろいろメモするためにブログ開始。

JavaScript再入門1- プロトタイプチェーンとコンストラクタ関数

JavaScriptは昔から触ってるけれど、いつも何となくググりながら場当たり的なコードを書いてやり過ごしてきてプロトタイプとかきちんと理解してないので、備忘も兼ねて勉強したことを記録してみる。

参考:最強オブジェクト指向言語 JavaScript 再入門!


1. オブジェクトはただのハッシュテーブル

オブジェクトは以下のようなコードで定義できる。

var obj = {key:value}

ここでvalueの部分には数値・テキスト・関数などを持ってこれるので、こんな書き方が可能。

var objA = {
    name:"tanaka"
    ,say:function(){alert("my name is " + this.name);}
}
objA.say();

2. Classはないけどプロトタイプチェーンがある

Class型言語の場合はClass定義をひな型としてオブジェクトを作るけれど、JavaScriptにクラスはない。そのかわり自身の上位(?)オブジェクトを自動的に参照するプロトタイプチェーンという機構がある。

var objA = {
    name:"tanaka"
    ,say:function(){alert("my name is " + this.name);}
}
var objB = {
    name:"suzuki"
}
var objC = {}
objB.__proto__ = objA
objC.__proto__ = objB

objA.say(); //"my name is tanaka"となる
objB.say(); //"my name is suzuki"となる
objC.say(); //"my name is suzuki"となる

ここでobjB.say()がコールされたときに、sayという関数はobjB自身はもっていないためそのプロトタイプであるobjAのsay関数が自動的に参照・コールされる。同様にobjC.say()の場合はobjB.nameとobjA.sayが使用される。
(ただし__proto__は標準仕様ではないらしく、通常は__proto__を使ったプロトタイプの設定はしないらしいけど・・・)

3. new演算子と関数を組み合わせてオブジェクトを生成する

ふつうはこんな風に書くらしい。(意味は分かるけど腹落ちしきれない)

var Person = function(name){
    this.name = name;
}
Person.prototype.sayHello = function(){
    alert("Hello " + this.name);
}
var o = new Person("suzuki")
o.sayHello();//"Hello suzuki"となる

「new演算子と組み合わせて関数をコールすることで、関数はコンストラクタ関数として実行され、オブジェクトの生成に利用される」とな。わかるようなわからないような・・・
new Person()をコールしたときに内部では(だいたい)こんなコードが動いているそう。

var obj = {};
obj.__proto__ = Person.prototype;
Person.apply(obj, arguments);
return obj;

__proto__というのは各オブジェクトが継承元の参照を保持するためのフィールドで、prototypeってのはクラス型言語でいうところのstaticともいうべき、各オブジェクトが参照すべきひな型という感じだろうか。3行目の意味はよくわからない、今後の課題とする。
元のスライドを丸パクリ写経した以下のコードだとここの動きがわかりやすい。

var Person = function(name){
	this.name = name;
}
Person.prototype.sayHello = function(){
	alert("Hello " + this.name);
}

var p = new Person("suzuki");
p.sayHello();//"Hello suzuki"

Person.prototype.name="tanaka";
p.sayHello();//"Hello suzuki"

delete p.name;
p.sayHello();//"Hello tanaka"

あやふやだった理解がだいぶしっかりした気がするけど、力尽きたので今日はここまで。

今後の課題

  1. Apply関数って何?
  2. (function() {})();とかいう記法
  3. thisのスコープの考え方