web-dev-qa-db-ja.com

__proto__はconstructor.prototypeとどう違うのですか?

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をどのようにチェックしますか?

154
xdevel2000

私は最近これに頭を巻き込もうとしており、ついにこの「地図」を思いつきました。

http://i.stack.imgur.com/KFzI3.png enter image description here

私はこれを最初に作ったのではないことを知っていますが、それを見つけることを理解することはより面白かったです:-)。とにかく、その後私は見つけた基本的に同じと思うこの別の図:

Javascriptオブジェクトレイアウト

私にとって最も驚くべきことは、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);
199
drodsou

constructorは、関数オブジェクトのprototypeプロパティが指すオブジェクトの事前定義された[[DontEnum]]プロパティであり、最初は関数オブジェクト自体を指します。

__proto__は、オブジェクトの内部[[Prototype]]プロパティ、つまり実際のプロトタイプと同等です。

new演算子を使用してオブジェクトを作成すると、その内部[[Prototype]]プロパティは、コンストラクター関数のprototypeプロパティが指すオブジェクトに設定されます。

つまり、.constructor.__proto__.constructor、つまりオブジェクトの作成に使用されるコンストラクター関数に評価され、学習したように、この関数のprotoypeプロパティを使用してオブジェクトの[[プロトタイプ]]。

.constructor.prototype.constructor.constructorと同じです(これらのプロパティが上書きされていない限り)。より詳細な説明については here を参照してください。

__proto__が使用可能な場合、オブジェクトの実際のプロトタイプチェーンをたどることができます。 JavaScriptは深い継承階層向けに設計されていないため、単純なECMAScript3でこれを行う方法はありません。

66
Christoph

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プロパティは作成されたオブジェクトには存在しないが、プロトタイプから継承されることに注意してください。

enter image description here

30
xorcus

Objectはイブ、Functionはアダム、アダム(Function)は自分のボーン(_Function.prototype_)を使用してイブ(Object)。では、誰がAdam(Function)を作成しましたか?-JavaScript言語の発明者:-)。

Utsainaの答えによると、もっと役立つ情報を追加したいと思います。

私にとって最も驚くべきことは、_Object.__proto___が_Function.prototype_ではなく_Object.prototype_を指していることを発見したことですが、それには十分な理由があると確信しています:-)

すべきではありません。 _Object.__proto___は_Object.prototype_を指すべきではありません。代わりに、Objecto、_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_

さらに、通常のクラスCatFunctionのインスタンス、つまり_Cat.__proto__ === Function.prototype_です。

上記の理由は、JavaScriptでクラスを作成するとき、実際にはFunctionのインスタンスでなければならない関数を作成しているだけだからです。 ObjectFunctionは特別なものですが、それでもクラスですが、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_)を作成しますか?それについて考えてください:-)

13
Peter Lee

なぜ人々があなたの理解の実際の問題についてあなたを修正しなかったのか本当に知りません。

これにより、問題を見つけやすくなります

それでは何が起こっているのか見てみましょう:

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つのことを覚えておいてください:

  1. new演算子を使用してオブジェクトを作成すると、その内部[[Prototype]]/proto__プロパティは、constructor functionまたは "creator"のprototype property(1)に設定されます(必要な場合)。

  2. 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

いい?

6
Royi Namir

すべての関数がプロトタイプを作成します。そして、その関数コンストラクターを使用してオブジェクトを作成すると、オブジェクトの__ proto __プロパティがその関数のプロトタイプを指すようになります。

2
Apoorv Nag

これらすべての数字が圧倒的だった場合、プロパティの意味を見てみましょう。

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プロパティは関数でのみ使用できることに注意してください。

STH.constructor

上記のプロトタイプオブジェクトには、constructor以外のプロパティはありません。このプロパティは、プロトタイプオブジェクトを作成した関数を表します。

var toy = new Gadget();

Gadget関数を作成するときに、{constructor: Gadget}などのオブジェクトも作成しました。これはGadget.prototypeのようなものではありません。 constructorはオブジェクトプロトタイプを作成した関数を参照するため、toy.constructorGadget関数を表します。 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}
// ...

STH .__ proto__

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
1