1

すべてのインスタンスには、作成に使用されたコンストラクターのプロトタイプへのリンクがあります。したがって、すべてのインスタンスがプロトタイプ メンバーを共有します。共有プロトタイプ メンバーへの変更が 1 つのインスタンスで行われると、他のすべてのインスタンスに反映されます。以下に示すように、これがプリミティブ型で機能しないように見える理由:

//creating an empty object type
function OBJTYPE(){};

//adding primitive value and reference value as a memeber to 
//the prototype of the object type
OBJTYPE.prototype.value = 0;
OBJTYPE.prototype.arr = ["red","green","blue"];

//creating instances of the object type
var obj1 = new OBJTYPE();
var obj2 = new OBJTYPE();

//outputting the prototype members through both the instances     
document.write(obj1.value + "<br />");  //0
document.write(obj2.value + "<br />");  //0
document.write(obj1.arr + "<br />");    //red,green,blue
document.write(obj2.arr + "<br />"); //red,green,blue

//changing value of primitive member
obj1.value = 1;  //creates a new instance property

//modifying the reference type member - pushing a value on the array
obj1.arr.push("black"); //modifies the prototype property

//outputting the prototype members through both the instances     
document.write(obj1.value + "<br />"); //1 //.value from instance
document.write(obj1.__proto__.value + "<br />"); //0 //.value from prototype
                                                 //works in Firefox, Safari, and Chrome
document.write(obj2.value + "<br />"); //0 //.value from prototype

document.write(obj1.arr + "<br />");   //red,green,blue,black
document.write(obj2.arr + "<br />");   //red,green,blue,black

上記のように、プリミティブ メンバーの値を変更すると、プロトタイプで同じ名前のプロパティを上書きする代わりに、valueonという名前の新しいインスタンス プロパティが作成されます。obj1したがって、プロパティにアクセスするobj1.valueと、プロトタイプ プロパティをマスクするインスタンス プロパティが返されます。そのため、2 つのインスタンス インスタンスは の異なる値を示しますvalue

ただし、これは参照型ではなく、上からわかるように同様に動作しません。なんで?

4

4 に答える 4

1

オブジェクトのプロパティに書き込むと、新しい値はプロトタイプではなくオブジェクトに格納されます。

あなたが持っている配列の問題は次のように機能します:

  1. obj1 に格納されている配列を取得し、配列を変更します: obj1.arr.push("black");

  2. obj1 のインスタンスに新しい値を書き込みます: obj1.arr = [1,2,3];

必要に応じて拡張します。


はい、必要に応じて、これを行う方法はたくさんあります。

1 私にとって最も明白なことは、同一のオブジェクトを作成したいということです。この場合、1 つのオブジェクトを作成するだけです。

var obj1 = {
 "arr": [],
 "value": 0
};
// I can garuntee any editing you do on obj1 will be reflected on obj2
var obj2 = obj1;

2 アクセサ メソッドのプロトタイプを作成します。

function OBJTYPE(){};

//adding primitive value and reference value as a memeber to 
//the prototype of the object type
OBJTYPE.prototype.value = 0;
OBJTYPE.prototype.arr = ["red","green","blue"];
OBJTYPE.prototype.proto = function (name, optValue) {
 if (arguments.length === 2) {
  return OBJTYPE.prototype[name] = optValue;
 }

 return OBJTYPE.prototype.proto[name];
};

var obj1 = new OBJTYPE();
var obj2 = new OBJTYPE();

obj1.proto('value', 1);  //on the prototype
// The rest will behave like desired

3 proto への直接リンクを保存します。

function OBJTYPE(){};

//adding primitive value and reference value as a memeber to 
//the prototype of the object type
OBJTYPE.prototype.value = 0;
OBJTYPE.prototype.arr = ["red","green","blue"];
OBJTYPE.prototype.proto = OBJTYPE.prototype;
//creating instances of the object type
var obj1 = new OBJTYPE();
var obj2 = new OBJTYPE();

//changing value of primitive member
obj1.proto.value = 1;  //on the prototype
// The rest will behave like desired

4 最後になりましたが、ES5 のメソッド getPrototypeOf を使用します

function OBJTYPE(){};

OBJTYPE.prototype.value = 0;
OBJTYPE.prototype.arr = ["red","green","blue"];
//creating instances of the object type
var obj1 = new OBJTYPE();
var obj2 = new OBJTYPE();

//changing value of primitive member
Object.getPrototypeOf(obj1).value = 1;  //on the prototype
// The rest will behave like desired
于 2012-10-28T08:23:56.047 に答える
1

プリミティブ値の場合のように新しい配列を割り当てるのではなく、配列にプッシュしていました。これは期待どおりに機能します。

obj1.value = 1; 
obj1.arr = [];

値を設定してもプロトタイプには設定されず、オブジェクト自体に設定されることに注意してください。

于 2012-10-28T08:24:15.727 に答える