まず最初に宣言します: JavaScript のすべてのオブジェクトにはコンストラクター属性とプロトタイプ属性があります。 constructor はオブジェクトのコンストラクターを指し、prototype はコンストラクターを使用して作成されたオブジェクト インスタンスのプロトタイプ オブジェクトを指します。
function Person(){ } var person = new Person(); Person.prototype = { constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this.name)} } person.sayName();
このコードではエラーが報告されます。sayName() が定義されていません。 『JavaScript Advanced Programming Second Edition』によると、オーバーライドされたプロトタイプによってコンストラクターと元のプロトタイプ間の接続が切断されるためです。ただし、上記のステートメントの順序を調整してみましょう。以下のように:
function Person(){ } //var person = new Person(); Person.prototype = { constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this.name)} } /*===========================================================*/ var person = new Person(); /*===========================================================*/ person.sayName(); // zxs alert(person.constructor) //function Object() { [native code]} or function Person() {} 取决与蓝色的语句是否有效
上記の 2 つのコード内の等号間のステートメントに注意してください。 2 番目の段落の順序でコードを記述すると、「zxs」が出力されます。この結果は、最初のケースで報告されたエラーが、コンストラクターと元のアイデアの間の接続が切断されたことによって発生したことを意味するものではないことを示しています。 。
Person.prototype = {}
これはもともとオブジェクトを定義する方法であり、JavaScript の各オブジェクトのコンストラクター属性はデフォルトで Object コンストラクターを指します。これは、プロトタイプ オブジェクトを書き換えるとコンストラクターとコンストラクターの間の接続が切断されることを示すのは難しくありません。元のプロトタイプの接続ですが、この接続が切断された後はsayName()関数にアクセスできなくなるわけではありません。
ここで、次の仮定があります。関数のプロトタイプ属性が指すプロトタイプ オブジェクトは、表示する新しく作成されたプロトタイプ オブジェクトとまったく同じではありません。関数を呼び出すと、まずプロトタイプ オブジェクトが現在の環境に存在するかどうかを確認し、存在しない場合は作成します。最後に、検索結果に基づいてプロトタイプ オブジェクトが返されます。このオブジェクトのプロパティとメソッドは、常にデフォルトのプロトタイプのプロパティとメソッド、つまり、で定義されているプロパティとメソッドを使用します。コンストラクター。呼び出されたメソッドまたはプロパティがデフォルトのプロトタイプに存在しない場合は、Person.prototype = {} で定義されたプロパティおよびメソッドが使用されます。
JavaScript はインタープリタ言語であり、ステートメントは順番に実行されます。コードの最初の部分では、 new キーワードを使用して新しいオブジェクトを作成するときに、 Person.prototype = {} は実行されません。これは、メソッドと定義されているプロパティが現在の実行環境に見つからず、メソッドがコンストラクターに存在しないため、エラーが発生します。変数と同様、値を代入する際にプログラムが実行されていない状態では使用できません。 2 番目の段落では、呼び出されたメソッドがすでに環境に存在しており、コンストラクターのプロトタイプ オブジェクトが作成されているため、結果を取得できます。
次のプログラムを見てください:
////////////////////////////////////////////////////////////////////////// function Person(){} /*===========================================================*/ var person = new Person(); Person.prototype.name = 'song'; /*===========================================================*/ //Person.prototype.sayName = function(){alert(this.name)}; Person.prototype = { constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this.name)} } person.sayName(); // error ////////////////////////////////////////////////////////////////////////// function Person(){ } /*var person = new Person();*/ Person.prototype.name = 'song'; /*Person.prototype.sayName = function(){alert(this.name)};*/ Person.prototype = { constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this.name)} } /*===========================================================*/ var person = new Person(); /*===========================================================*/ person.sayName(); // zxs
ここから、 Person.prototype.name = '' を使用すると、オブジェクト リテラルとこのメソッドで定義されたプロトタイプ オブジェクトの両方がある場合、オブジェクトが作成された場所に関係なくアクセスできることがわかります。定義されたオブジェクトが最終値として使用されます。また、プロトタイプ オブジェクトのオブジェクト リテラル定義を使用した後、オブジェクトにアクセスするには、オブジェクトを作成するステートメントの前にその定義を指定する必要があります。
インスタンスは、プロトタイプ オブジェクトのプロパティやメソッドにアクセスできません。特に、プロトタイプ オブジェクトをオーバーライドするとコンストラクターと元のプロトタイプ間の接続が切断されるためです。
function Person(){ } var person = new Person(); Person.prototype = { //constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this.name)} } person.sayName();
上記のコードのコンストラクター関数のプロトタイプは、オブジェクトのインスタンス化時には空であり、デフォルトのプロパティ以外のプロパティはありません。コンストラクターのプロトタイプをオーバーライドすると、コンストラクターと元のプロトタイプの間の接続が切断されます。
new 演算子を使用した後、コンストラクターのプロトタイプ オブジェクトのプロパティとメソッドが person オブジェクトに追加されました。上記のメソッドは関数プロトタイプに新しいプロパティやメソッドを追加する際に動的ではないため、人は新しく追加されたプロパティやメソッドにアクセスできません。
プロトタイプ オブジェクトを書き直すと、次のコードのようになります:
var o = { name : 'zxs' } var obj = o; o = {} console.log(o.name);
オブジェクトは参照型、「=」は代入演算子、演算順序は右から左となるため、この時の出力値は不定となります。 o={} は、o の点が変更され、空のオブジェクトであることを意味します。
Person.prototype.mothed = function() {} と Person.prototype={mothed:function(){}} の違いは、arr = [] と arr.push() と同じです。一方、後者は自分自身を完全に変えます。