__proto__・prototype (1) : JavaScript

Pocket

JavaScriptのプロトタイプについてのメモ。

JavaScriptの関数はオブジェクト。そのことを強調するために本記事は関数を関数オブジェクトと呼ぶ。
また本記事では関数オブジェクトからnew演算子で生成したオブジェクトをインスタンスと呼ぶ。

次の4点がこの記事のポイント。

  • __proto__ プロパティとprototypeプロパティは異なる。
  • __proto__ プロパティはプロトタイプチェーン[1]をたどるためにある。
    一方prototypeプロパティは関数オブジェクトを拡張するためにある。
  • new演算子でインスタンスの生成を想定した関数オブジェクトをコンストラクタと呼ぶ。
    インスタンスを生成するときに関数オブジェクト(つまりコンストラクタ)のprototypeプロパティがインスタンスの__proto__プロパティに設定される。[2],[3],[4]
  • インスタンスは__proto__プロパティを持つがprototypeプロパティは持たない。 関数オブジェクトは__proto__プロパティとprototypeプロパティの両方を持つ。

      __proto__ prototype
    インスタンス ×
    関数オブジェクト
// 関数オブジェクト定義
var Foo = function () {
}
// プロトタイプにメソッドを定義
Foo.prototype.hoge = function () {
    return 'Hello';
}

//Fooをコンストラクタとしてインスタンスを生成。
var o = new Foo();
o.__proto__ === Foo.prototype; // true
o.hoge(); // Hello
// インスタンスはprototypeプロパティは持たない
o.prototype // undefined

__proto__とprototypeの分かり易い記事の紹介と引用。

JavaScriptにおける「プロトタイプ・オブジェクト」って言葉は、まったく異なる2つの意味で使われています。混乱を避けるために、ここでは、「__proto__オブジェクト」と「prototypeオブジェクト」という言葉を使い分けます。この2つは別物です!

» プログラマのためのJavaScript (7):プロトタイプ継承の正体 – 檜山正幸のキマイラ飼育記

コンストラクタのの分かり易い記事の紹介と引用。

さてところで、そもそもコンストラクタって何でしょう。JavaScriptのコンストラクタは、実際のところ単なる関数です。
しかも、「コンストラクタ」という言葉は関数の種別を表しているのではなくて、関数の使用法の種別を表しているのです。

» プログラマのためのJavaScript (8):オブジェクト生成の仕組み – 檜山正幸のキマイラ飼育記

インスタンスの__proto__プロパティには生成に使われた関数オブジェクトのprototypeオブジェクトが設定される。
関数オブジェクトは必ずprototypeオブジェクトを持つ[5]。よってすべてのインスタンスの__proto__プロパティには生成に使われた関数オブジェクトのprototypeオブジェクトが設定されている。
全てのインスタンスは__proto__を持つ。しかし処理系によっては__proto__を見せないものもある(IEなど)。

__proto__とprototypeについては__proto__・prototype (2) : JavaScriptにも書いている。

参考リンク 追記 : 2011.03.10

prototypeと__proto__に関するとても分かりやすい記事。
» Javascript Object Hierarchy
» prototypeと__proto__ – mfumiの日記

1. プログラマのためのJavaScript (7):プロトタイプ継承の正体 – 檜山正幸のキマイラ飼育記はプロトタイプチェーンについて下記のように記載している。
「「JavaScriptには、クラスとその継承はないが、プロトタイプベースの継承をサポートしている」と、まー、これはよく言われる決まり文句です。がしかし、JavaScriptにおけるアレを継承と呼んでいいものかどうか? 「継承」といえば、多くの人が通常の継承、つまりクラスベースの継承をイメージするでしょうし、無意識に通常の継承とのアナロジーを追うことになるでしょう。これは危険だと思いますよ。

「プロトタイプ」とか「継承」という言葉から連想する常識的なイメージは全部捨てて、事実を白紙から眺めましょう。その事実とは、「JavaScriptには、実行時プロパティ検索のメカニズムがある」と、それだけです。」

2. インスタンスのプロトタイプチェーン用のプロパティ__proto__はコンストラクタ(関数オブジェクト)のprototypeプロパティを参照する。コンストラクタの静的メンバをインスタンからプロトタイプチェーンで参照することはできない
2010.03.10 追記
function Foo () {
}
Foo.hoge = function () {
return ‘static’;
}
var foo = new Foo();
foo.hoge(); // Error
3. prototypeと__proto__については下記サイトに詳しい説明がある。
»prototype と __proto__ と constructor, Property Accessor とメソッド呼び出し, JavaScript における mix-in – ema log(2008-01-21)

4. オブジェクトリテラル{}を用いたインスタンス生成var o = {}は、関数オブジェクトからnew演算子を使いインスタンスを生成する処理-オブジェクト定義とインスタンス化-を同時に行うことと同じである。
詳しくはオブジェクトリテラル : JavaScriptを参照。
5. 継承という言葉が適当かを別にすると関数オブジェクトはObjectオブジェクトを継承している。

コメント

No comments yet.

コメントの投稿

改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。