Hatena::ブログ(Diary)

guccyonikki このページをアンテナに追加 RSSフィード

2007-11-09

__proto__とprototypeについて

Kanasan.jsで__proto__とprototypeの関連について調べる

っていう宿題があったのを思い出し、

調べてみたので以下解説。


オブジェクトの特徴として、

・全てのオブジェクトは__proto__プロパティを持ちます。

そして

・全ての関数オブジェクトprototypeプロパティを持ちます。

またnewによって作成されたオブジェクト

__proto__プロパティにはその関数prototypeがセットされ

__proto__はconstructorプロパティを持ちます。

このconstructorプロパティはnewした関数オブジェクトを指しています。



では次にコード的に見ていきましょう。

以下のような関数(クラス)Parent,Childがあったとします。

function Parent() { }

function Child() { }
Child.prototype = new Parent();

単純な継承関係ですね。

そしてChildクラスからオブジェクトを作成します。

var myobj = new Child();

ここまでの動作で役者としては4個のオブジェクトが登場します。


オブジェクトを()で囲みその中に関数名(クラス名)、

関数オブジェクトを[]で囲みその中に関数名で表示という表記で、

上記のコードの関係を書き出してみます。

=は代入ではなく、右辺のオブジェクトと等しいと読み替えてください。

(?).constructor = [Parent]
[Parent].prototype = (?)
(Parent).__proto__ = [Parent].prototype = (?)

[Child].prototype = (Parent)
(Child).__proto__ = [Child].prototype = (Parent)
(Child).__proto__.constructor = [Child]
(Child).constructor = 'undefined'

という関係が成り立ちます。


追記:画像にしてみました。

f:id:guccyon:20071112142833j:image:w450


そしてprototypeチェーンとは、

プロパティの参照時に辿っていく連鎖の事で

上記の場合、(Child)のプロパティhoge

  1. this.hoge
  2. (Child).__proto__.hoge = (Parent).hoge = [Child].prototype.hoge
  3. (Child).__proto__.__proto__.hoge = (Parent).__proto__.hoge = (?).hoge

の順に探していきます。(= は全て同じものを指している)

(?)については多重に継承している場合は、同様に__proto__で繋がっていきます。

継承が終わった時点で(?)はnullになります。

プロパティの参照時、(?)がnullの場合そのプロパティはundefinedという値になります。



とまぁ、ここまでが調べた答え。


そして実際に動作の確認。(FireFox2.0を利用)

var Parent = function(){}
var Child = function(){}
Child.prototype = new Parent();

alert(new Child().__proto__ === Child.prototype);   # trueとなる

うん。調べた通りだ。

次に少しいじわるをしてprototypeにnullを突っ込んでみた。

Child.prototype = null;

alert(Child.prototype === null);   # true
alert(new Child().__proto__ === null); # false
alert(new Child().__proto__ === Child.prototype); # false

あれ・・??

てっきり__proto__にはnullが入って

チェーンが繋がらないものと思ったけど。

2つ目と3つ目の結果からnullではないんだ。

調べるとどうやら、コンストラクタ

prototypeから__proto__へ値をセットする時、

prototypeオブジェクトでなければObject.prototype

セットするという仕様らしい。

alert(new Child().__proto__ === Object.prototype); # true

期待通りになった。

以上。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/guccyon/20071109/name