プロトタイプってなんていうか、ガンダムの後付機体みたいだよね。プロトタイプリックディアス、プロトタイプゼータガンダム、プロトタイプ……他にいましたっけ?

銀河月下美人のじぇんとるめんのみんな! 元気にしてたかな?
今日もうどんさんの経験をまとめる簡単な作業を始めるよ。今回はJavaScriptだよ。

newって結局何を生成するのよ

function f(){thia.a = 10;};

var obj = new f();

このコードのobjは結果として以下のような構造になるらしいよ。

{
a:10,
__proto__:f.prototype
};

関数をnewする

{}生成

{}をthisに代入

関数を普通に実行しちゃう(ここでthisキーワードを使って値を入れると、{}に反映されるわけね)

関数のprototypeを__proto__という名前で{}に入れる(関数のprototypeがなんらかの形で書き換えられてたら、それは{}に影響するということね)

{}を戻り値にする


っていう流れらしいよ。

prototype、__proto__、紛らわしい名前つけやがって

var obj = {};

obj.__proto__ //Object

__proto__ってなんだよ、って思ってデバッガ(Chrome7)で色々試してみたんだけど、どうやらオブジェクトを生成すると暗黙的に__proto__を生成するみたい。
で、prototypeはオブジェクト達の共通の領域らしーよ。prototypeに関数を置くと効率が良いってぱっちゃが言ってた。

__proto__ってやつにオブジェクトを入れると面白いのね。

var obj = {};
obj.a //undefined

obj.__proto__ = {a:10};

obj.a //10

obj.aを実行する時、まず自分のオブジェクトの中からaって名前があるかどうかを検索するらしいよ。
んで、もしなかったらオブジェクトの中にある__proto__のオブジェクトからaって名前を検索するらしいよ。
__proto__にもaがなければ、さらに__proto__の中の__proto__みたいに延々と検索していくらしいよ。
もしaの名前が見つからなかったら、その時初めてaはundefinedであると認識するみたい。
デバッガで見る限り、最後のオブジェクトには__proto__は存在しなかったね……ちなみにobj.__proto__にundefinedを代入してみたけど、なんの反応もなかったよ

つまりこういう事かなぁ

a「値を渡したまえ、いい子だから、さぁ」


Object「お願い! __proto__!(ドンドン」


a「はっはっはっ、どこへ行こうというのかね」


Object.__proto__「パズー! __proto__に捨てて!」


a「(パーン)その値を大事に持ってろ! 小娘の命と引き換えだ!」





a「終点が__proto__なしとは上出来じゃないか」


Object.__proto__.__proto__「これが__proto__なしですって? ここはお墓よ。あなたはundefined」


a「値はundefined。何度でも蘇るさ」

ひどい話

__proto__を使うとオブジェクト指向の継承が使えるようになるんだけど、それでつまづいたお話でもしましょう。

var sup = function(){
this.a = 10;
};

var sub = function(){};
sub.prototype = new sup();

sub.a //10

継承を行なうのは簡単で、スーパークラスのコンストラクタで生成したオブジェクトを、サブクラスのprototypeにつっこめばいいのです。らくちんらくちん。
ちなみに知ってる? superってjsの予約語らしいよ。ちょうしゃらくさいよね。

var sup = function(){
a();
};

function sub(){};
sub.prototype = new sup();

var a = function(){};

aが出てきましたね。
当たり前の話なんですけど、new sup();を実行する時、aってundefinedなんですよね。で、コンストラクタ内にa();があるとエラーが起きるわけです。
これでずーっと悩んでました。だって意味不明なエラーメッセージを吐くんですもの……。素直に「aがundefinedだよごしゅじんさまー」って言って欲しいです。
Googleって使う人には優しいけど開発者には優しくないと思うのよね。別にGoogleに限った話ではないんだろうけどさー。
もっと! 開発に! お砂糖のような! 優しさを! と常々思います。優しい開発環境をつくれる大人に、私はなりたい。

var sup = function(){
a();

sup.apply(this);
};

function sub(){};
sub.prototype.__proto__ = sup.prototype;

var a = function(){};

というわけで以上のようにして解決しましたよ。すごい微妙だけどね……
sup.applyを使ってsupのコンストラクタを自分のthisで使えるようにして、コンストラクタ上で生成される変数をぶんどってきます。
applyだけだとprototypeにある関数とかが使えないので、sup.prototypはsub.prototype.__proto__に入れてあげますよ。
sub.prototypeに直接入れても動くには動くんだけど、sub.prototypeを変更するとスーパークラスのsupまで影響を及ぼす恐れがあるから、__proto__に入れてあげた方が安全なのですよ。


まぁ、安全とか言ってるけど、jsってほぼぜんぶpublicな状態だよね。社会の窓から長いのが出てますよクラスの変態さん……安全なんて言葉はあってないようなもんです。あぁ、privateという概念がなつかしい(遠い目
コンストラクタにメソッド全部書いて、クロージャで値をいじるようにすればprivateを再現できそうではある。でもメモリめっちゃ食いそうだよなぁ……それなら性能を重視してコンピュータに支配されながらコードを書く方が良いような気がしないでもない。

個人的意見として

JavaScriptスクリプト言語C++だと思ってる。
いや他のスクリプト言語、ほとんどいじった事ないから分かんないけどね……でも少なくともJavaよりはメンドクサイ事おおよ、jsちゃんは。
でも嫌いってわけじゃねーのよ? ぼくjs大好きよ。でももうちょっとなんとかならんのかなぁ、と思う事は多々あるような。ないような。そんな感じです。