5

新しいオブジェクトを作成するときにプロトタイプ オブジェクトを選択できるメソッドがあります (「Javascript: The Good Parts」ブックからコピー)。

Object.create = function(o) {
    var F = function() {};
    F.prototype=o;
    return new F();
}

さて、私はオブジェクトを持っているとしましょう:

var car = {
   model: "Nissan"
};

そして、"Create" メソッドを使用して、このオブジェクトに基づいて新しいオブジェクトを作成します。

var car1 = Object.create(car);

次に、car にプロパティを追加すると、car1 に動的に追加されます (動的プロトタイピング)。たとえば、次のようになります。

car.year=2011;      // Gets added to "car"...
alert(car1.year);   // ... Is also avaialable to car1

Q1) この動作は、car のプロトタイプに「年」が追加されたことを示しています。これが car1 で使用できる理由です。これは正しいです?そうでない場合、「年」はどこに追加され、「車」と「車 1」の両方で使用できるのはなぜですか?

また、委譲の規則に従って、メソッドがオブジェクトで見つからない場合、そのプロトタイプを検索し、Object.prototype に到達するまでチェーンのすべてのプロトタイプをチェックします。したがって、次のように入力すると、次のようになります。

Object.prototype.originCountry = "Japan";
alert(car.originCountry);   // Outputs Japan
alert(car1.originCountry);  // Outputs Japan

ここまでは順調ですね; ただし、そうする場合:

Object.carColor= "White";
alert(car.carColor);   // Error!

Q2) 「車」にプロパティを追加すると (上記のcar.yearの例を参照)、車のプロトタイプに追加されます。ただし、オブジェクトにプロパティを追加すると、オブジェクトのプロトタイプに追加されませんか? 追加される場合Object のプロトタイプに、なぜ委任のルールに従って「車」に利用できないのですか?

なぜこうなった?

4

3 に答える 3

5

これを行うとき:

Object.carColor = "White";

その場合、プロパティはのプロトタイプcarColorに追加されません。Object現在はのプロパティですObject。あなたが何を期待するかを見るために、あなたがすることは次のとおりです:

Object.prototype.carColor = "White";

その後:

alert(({}).carColor); // Will alert "White"

つまり、ここで何が起こるかということです。を含めて作成されたオブジェクト{}(これは空のオブジェクトにすぎません)はの新しいインスタンスであるObjectため、のプロトタイプに設定されているもののプロパティを共有しますObject

あなたの関数がどのようにObject.create機能するかについて。行ごとに見てみましょう。

 1. var F = function() {};

新しい関数、本質的に空白のオブジェクトを作成するだけです。関数を使用する理由は、関数を呼び出しと組み合わせて、関数がコンストラクターとして機能するオブジェクトの新しいインスタンスを作成{}できるためです。new

2. F.prototype=o;

新しい空白関数のプロトタイプを、作成したオブジェクトに設定します。さて、これは純粋に参照です。ディープコピーではありません。つまり、オブジェクトoが変更されると、オブジェクトのインスタンスも変更されます(実際には変更されませんが、変更されるように見えます。これについては後で詳しく説明します)。

3. return new F();

ここで、渡したオブジェクトとしてプロトタイプを持つ、その関数の新しいインスタンスを作成するだけです。

次のことを行う場合:

var car1 = Object.create(car);

car1プロトタイプが持っているオブジェクトを取得しますcar。したがって、これを行うと:

car.year = 2011

それはcar1変化のようではありません。プロトタイプが変更を参照するのは、オブジェクトに似ています。したがって、次のようなことを行うと、次のようになります。

car1.year

呼び出されたプロパティが検索され(最初にプロトタイプで、次にオブジェクトで)、プロトタイプにそのプロパティyearがあるため、car1.yearが返され2011ます。

つまり、結論は次のとおりです。

  1. プロトタイプはインスタンス間で共有されます。
  2. のプロパティを変更Objectしても、インスタンスが変更されることはありません。
于 2012-04-26T07:14:31.540 に答える
1

最初の例では、car1becausecar === F.prototypeとのプロトタイプに追加していますcar1 instanceof F。Q1へ:はい。

Objectは、すべてのオブジェクトのコンストラクター関数Fですcar1。に何かを追加するとObject.prototype、それはすべてのオブジェクトで使用可能になります-それがすべきでない理由です。そのような列挙不可能なプロパティは、すべてのfor-in-loopを台無しにします。コンストラクター関数のプロパティを設定すると、Objectそれから継承するものは何も変更されません。忘れないでください:プロトタイプ設定のパラメータではなく、関数にObject等しい。のようなものです。Fonew Object()Object.create(Object.prototype)

于 2012-04-26T07:10:17.287 に答える
0

この関数では、プロトタイプオブジェクトを選択して、nmewオブジェクトコンストラクターを作成し、オブジェクト引数をプロトタイプとして選択して、コンストラクターに基づいて新しいオブジェクトを返すことはできません。

その新しいオブジェクトは、オブジェクト引数からメソッドとプロパティを継承します。これは、他のオブジェクトから継承する新しいオブジェクトを作成できるようにするためです。

これが機能する理由(ちなみに、Objectはコアjavascriptオブジェクトであり、拡張しないでください)

Object.prototype.originCountry = "Japan";
alert(car.originCountry);   // Outputs Japan
alert(car1.originCountry);

そしてこれはしません

Object.carColor= "White";

これは、最初にObjectのプロトタイプオブジェクトを拡張するためです。つまり、Objectコンストラクターを使用したオブジェクトビルドは、これらのメソッドとプロパティを継承します。

後者の場合、オブジェクトコンストラクターから作成されたオブジェクトに渡されない静的関数を呼び出します。

Javascriptでのプロトタイプの継承についてもっと読むことをお勧めします。ここにいくつかのリンクがあります。

http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=xEJ2PwtH2Oh

http://unscriptable.com/2007/04/17/inheritance-explained/

于 2012-04-26T07:10:36.223 に答える