function Gadget(name, color)
{
this.name = name;
this.color = color;
}
Gadget.prototype.rating = 3
var newtoy = new Gadget("webcam", "black")
newtoy.constructor.prototype.constructor.prototype.constructor.prototype
常に評価= 3のオブジェクトを返します。
しかし、私が次のことをすると:
newtoy.__proto__.__proto__.__proto__
チェーンはnull
を返します。
また、Internet Explorerでは、__proto__
プロパティがない場合、nullをどのようにチェックしますか?
私は最近これに頭を巻き込もうとしており、ついにこの「地図」を思いつきました。
http://i.stack.imgur.com/KFzI3.png
私はこれを最初に作ったのではないことを知っていますが、それを見つけることを理解することはより面白かったです:-)。とにかく、その後私は見つけた基本的に同じと思うこの別の図:
私にとって最も驚くべきことは、Object.__proto__
に指差す Function.prototype
、 の代わりに Object.prototype
、しかし、それには十分な理由があると確信しています:-)
誰かがそれをテストしたい場合のために、ここにも画像に記載されているコードを貼り付けます。いくつかのプロパティがオブジェクトに追加され、ジャンプ後の位置を簡単に把握できることに注意してください。
Object.O1='';
Object.prototype.Op1='';
Function.F1 = '';
Function.prototype.Fp1 = '';
Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';
mycat = new Cat();
o = {};
// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);
constructor
は、関数オブジェクトのprototype
プロパティが指すオブジェクトの事前定義された[[DontEnum]]プロパティであり、最初は関数オブジェクト自体を指します。
__proto__
は、オブジェクトの内部[[Prototype]]プロパティ、つまり実際のプロトタイプと同等です。
new
演算子を使用してオブジェクトを作成すると、その内部[[Prototype]]プロパティは、コンストラクター関数のprototype
プロパティが指すオブジェクトに設定されます。
つまり、.constructor
は.__proto__.constructor
、つまりオブジェクトの作成に使用されるコンストラクター関数に評価され、学習したように、この関数のprotoype
プロパティを使用してオブジェクトの[[プロトタイプ]]。
.constructor.prototype.constructor
は.constructor
と同じです(これらのプロパティが上書きされていない限り)。より詳細な説明については here を参照してください。
__proto__
が使用可能な場合、オブジェクトの実際のプロトタイプチェーンをたどることができます。 JavaScriptは深い継承階層向けに設計されていないため、単純なECMAScript3でこれを行う方法はありません。
JavaScriptのプロトタイプ継承は、__proto__
プロパティによって参照されるオブジェクトのコンテンツを各オブジェクトが継承しているという意味で、__proto__
プロパティに基づいています。
prototype
プロパティは、Function
オブジェクト専用であり、new
演算子を使用してFunction
をコンストラクターとして呼び出す場合にのみ特別です。この場合、作成されたオブジェクトの__proto__
は、コンストラクターのFunction.prototype
に設定されます。
つまり、Function.prototype
に追加すると、__proto__
がFunction.prototype
を参照しているすべてのオブジェクトに自動的に反映されます。
コンストラクタのFunction.prototype
を別のオブジェクトに置き換えると、既存のオブジェクトの__proto__
プロパティがnot更新されます。
__proto__
プロパティには直接アクセスしないでください。代わりに Object.getPrototypeOf(object) を使用してください。
最初の質問に答えるために、__proto__
およびprototype
参照のカスタムダイアグラムを作成しました。残念ながら、stackoverflowでは「10未満の評判」の画像を追加できません。たぶん他の時間。
[編集]図は、[[Prototype]]
の代わりに__proto__
を使用します。これは、ECMAScript仕様が内部オブジェクトを参照する方法だからです。あなたがすべてを理解できることを願っています。
図を理解するのに役立つヒントを次に示します。
red = JavaScript Function constructor and its prototype
Violet = JavaScript Object constructor and its prototype
green = user-created objects
(first created using Object constructor or object literal {},
second using user-defined constructor function)
blue = user-defined function and its prototype
(when you create a function, two objects are created in memory:
the function and its prototype)
constructor
プロパティは作成されたオブジェクトには存在しないが、プロトタイプから継承されることに注意してください。
Object
はイブ、Function
はアダム、アダム(Function
)は自分のボーン(_Function.prototype
_)を使用してイブ(Object
)。では、誰がAdam(Function
)を作成しましたか?-JavaScript言語の発明者:-)。
Utsainaの答えによると、もっと役立つ情報を追加したいと思います。
私にとって最も驚くべきことは、_
Object.__proto__
_が_Function.prototype
_ではなく_Object.prototype
_を指していることを発見したことですが、それには十分な理由があると確信しています:-)
すべきではありません。 _Object.__proto__
_は_Object.prototype
_を指すべきではありません。代わりに、Object
o
、_o.__proto__
_のインスタンスは_Object.prototype
_を指す必要があります。
(JavaScriptでclass
およびinstance
という用語を使用することをお許しください。
クラスObject
自体はFunction
のインスタンスだと思います。だからこそ_Object.__proto__ === Function.prototype
_です。したがって:Object
はEveで、Function
はAdamです。Adam(Function
)は自分のボーン(_Function.prototype
_)を使用してEve(Object
)。
さらに、クラスFunction
自体もFunction
自体のインスタンス、つまり_Function.__proto__ === Function.prototype
_であるため、_Function === Function.constructor
_
さらに、通常のクラスCat
はFunction
のインスタンス、つまり_Cat.__proto__ === Function.prototype
_です。
上記の理由は、JavaScriptでクラスを作成するとき、実際にはFunction
のインスタンスでなければならない関数を作成しているだけだからです。 Object
とFunction
は特別なものですが、それでもクラスですが、Cat
は通常のクラスです。
要因として、GoogleではChrome JavaScriptエンジン、次の4:
Function.prototype
_Function.__proto__
_Object.__proto__
_Cat.__proto__
_それらはすべて他の3と_===
_(絶対的に等しい)で、値はfunction Empty() {}
です
_> Function.prototype
function Empty() {}
> Function.__proto__
function Empty() {}
> Object.__proto__
function Empty() {}
> Cat.__proto__
function Empty() {}
> Function.prototype === Function.__proto__
true
> Function.__proto__ === Object.__proto__
true
> Object.__proto__ === Cat.__proto__
true
_
OK。次に、誰が特別なfunction Empty() {}
(_Function.prototype
_)を作成しますか?それについて考えてください:-)
なぜ人々があなたの理解の実際の問題についてあなたを修正しなかったのか本当に知りません。
これにより、問題を見つけやすくなります
それでは何が起こっているのか見てみましょう:
var newtoy = new Gadget("webcam", "black")
newtoy
.constructor //newtoy's constructor function is newtoy ( the function itself)
.prototype // the function has a prototype property.( all functions has)
.constructor // constructor here is a **property** (why ? becuase you just did `prototype.constructor`... see the dot ? ) ! it is not(!) the constructor function !!! this is where your mess begins. it points back to the constructor function itself ( newtoy function)
.prototype // so again we are at line 3 of this code snippet
.constructor //same as line 4 ...
.prototype
rating = 3
それでは、この__proto__
を見てみましょう
その前に、__proto__
に関する2つのことを覚えておいてください:
new
演算子を使用してオブジェクトを作成すると、その内部[[Prototype]]
/proto__
プロパティは、constructor function
または "creator"のprototype
property(1)に設定されます(必要な場合)。
JS内でハードコーディングされています—:Object.prototype.__proto__
はnull
です。
これらの2つのポイントを「bill
」と呼びましょう。
newtoy
.__proto__ // When `newtoy` was created , Js put __proto__'s value equal to the value of the cunstructor's prototype value. which is `Gadget.prototype`.
.__proto__ // Ok so now our starting point is `Gadget.prototype`. so regarding "bill" who is the constructor function now? watch out !! it's a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it's the `function Object(){...}`. Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it's `Object.prototype`. just remember that when Gadget.prototype was created , it's internal `__proto__` was refered to `Object.prototype` becuase as "bill" says :"..will be set to the `prototype` property of its `constructor function`"
.__proto__ // Ok so now our satrting point is `Object.prototype`. STOP. read bullet 2.Object.prototype.__proto__ is null by definition. when Object.prototype ( as an object) was created , they SET THE __PROTO__ AS NULL HARDCODED
いい?
すべての関数がプロトタイプを作成します。そして、その関数コンストラクターを使用してオブジェクトを作成すると、オブジェクトの__ proto __プロパティがその関数のプロトタイプを指すようになります。
これらすべての数字が圧倒的だった場合、プロパティの意味を見てみましょう。
STH.prototype
新しい関数を作成すると、空のオブジェクトが並行して作成され、[[Prototype]]
チェーンで関数にリンクされます。このオブジェクトにアクセスするには、関数のprototype
プロパティを使用します。
function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}
prototype
プロパティは関数でのみ使用できることに注意してください。
上記のプロトタイプオブジェクトには、constructor
以外のプロパティはありません。このプロパティは、プロトタイプオブジェクトを作成した関数を表します。
var toy = new Gadget();
Gadget
関数を作成するときに、{constructor: Gadget}
などのオブジェクトも作成しました。これはGadget.prototype
のようなものではありません。 constructor
はオブジェクトプロトタイプを作成した関数を参照するため、toy.constructor
はGadget
関数を表します。 toy.constructor.prototype
と記述し、{constructor: Gadget}
を再び取得しています。
したがって、悪循環があります。toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype
を使用でき、常にGadget.prototype
になります。
toy
.constructor // Gadget
.prototype // {constructor: Gadget}
.constructor // Gadget
.prototype // {constructor: Gadget}
// ...
prototype
は関数固有のプロパティですが、__proto__
はObject.prototype
にあるため、すべてのオブジェクトで使用できます。オブジェクトを作成できる関数のプロトタイプを指します。
[].__proto__ === Array.prototype
// true
({}).__proto === Object.prototype
// true
ここで、toy.__proto__
はGadget.prototype
です。 Gadget.prototype
はオブジェクト({}
)であり、オブジェクトはObject
関数(上記の例を参照)で作成されるため、Object.prototype
を取得します。これはJavaScriptの上位オブジェクトであり、その__proto__
はnull
のみを示すことができます。
toy
.__proto__ // Gadget.prototype (object looking like {constructor: Gadget})
.__proto__ // Object.prototype (topmost object in JS)
.__proto__ // null - Object.prototype is the end of any chain