2017-05-03 1 views
7

プロトタイプのインスタンスを2つ作成し、プロトタイプの関数を変更し、両方のインスタンスに反映された変更(Great)を作成しました。 しかし、関数を削除してプロトタイプを変更しても、その関数は既存のインスタンスにはまだ存在していました。予想通り Javascript:プロトタイプの変更は既存のインスタンスには影響しません

function A() { 
 
    this.name = "cool"; 
 
} 
 

 
A.prototype = { 
 
    howCool: function() { 
 
    return this.name + "er"; 
 
    } 
 
}; 
 

 
var a1 = new A(), 
 
    a2 = new A(); 
 

 
a1.name = "hot"; 
 
//line1 
 
console.log(a1.howCool()); 
 
//line2 
 
console.log(a2.howCool()); 
 

 
A.prototype = {}; 
 

 
//line3 
 
console.log(a1.howCool()); 
 

 
//line4 
 
var a3 = new A(); 
 
console.log(a3.howCool());

ライン1及び2は、作業しているとバック空にprotoypeを設定した後、ライン4が予想される未定義を示しています。 3行目はまだ関数定義を示しています。

+6

あなたはプロトタイプオブジェクトを変更していないので、新しいオブジェクトを作成しています。 – Bergi

+0

[instanceof'](http://stackoverflow.com/q/14568239/1048572)と[Javascriptプロトタイプを正しく定義する方法](http://stackoverflow.com/q/17474390/)と同じ混乱も参照してください。 1048572) – Bergi

+2

実際に、新しいオブジェクトに対してprototypeプロパティを再割り当てしました。古いものはまだ存在します。 – abhishekkannojia

答えて

5

実質的には、Aの新しいオブジェクトを指すようにprototypeプロパティを再割り当てしています。これは古いオブジェクトには影響しないため、以前のインスタンスには影響しません。

ここには何が起こっているのかが示されています。

function A() { 
    this.name = "cool"; 
} 

A.prototype = { 
    howCool: function() { 
    return this.name + "er"; 
    } 
}; 

var a1 = new A(), 
    a2 = new A(); 

状況は以下の通りです:

before

次に、このコードの実行後:新へ

A.prototype = {}; 

var a3 = new A(); 

A.prototypeポイントこのコードを実行した後

オブジェクトですが、[[Prototype]]古いインスタンスのプロパティは、古いオブジェクトを指しています。

after

あなたが実際にメソッドを削除したい場合は、新しいものを指して、元のオブジェクトを編集する必要がありません。実際にこのような何かがうまくいく、プロトタイプからhowCool()方法を削除するには

与えるだろう
delete A.prototype.howCool 

finally

を今なa3、そしてなど任意の将来のインスタンスを、以前のオブジェクトはすべて同じオブジェクトを指していますが、そのオブジェクトにはhowCool()メソッドがありません。

0

あなたはプロトタイプが、それは昔のインスタンスに影響する変更した場合

function A(){ 
 
    this.name = "cool"; 
 
} 
 

 
A.prototype = { 
 
    howCool : function(){ 
 
     return this.name + "er"; 
 
    } 
 
}; 
 

 
var a1 = new A(), 
 
    a2 = new A(); 
 

 
a1.name = "hot"; 
 
//line1 
 
console.log(a1.howCool); 
 
//line2 
 
console.log(a2.howCool); 
 

 
delete A.prototype.howCool; 
 

 
//line3 
 
console.log(a1.howCool); 
 

 
//line4 
 
var a3 = new A(); 
 
console.log(a3.howCool);

+0

または、 '.prototype.howCool = undefined;'です。 – GramThanos

1

まあdelete演算子を使用してみてください、しかし、あなたは新しいものを作成する場合、それは昔のインスタンスには影響しません。

ですから、書くとき:

A.prototype = {}; 
//line3 
console.log(a1.howCool); 

オブジェクトa1.__proto__はまだそれがundefinedを記録していない理由です、初期A.prototypeを指します。

そして、あなたが書いた:

//line4 
var a3 = new A(); 
console.log(a3.howCool()); 

新しいインスタンスa3あなたはùndefined`だ理由です新しい作成A.prototypeを使用しています。あなたが間にリンクがあることを知っているよう


(__proto__の使用量は、生産コードでは避けるべきであるとして説明以下の実験や概念の理解のためだけであることに注意してください。)ここで

0

は、可能な説明ですオブジェクト(この場合はa1)と、オブジェクトが作成されるコンストラクタ関数のプロトタイプ(この場合はA)との間の関係を示す。 このリンクは__proto__またはdunder protoと呼ばれています。したがって、この場合はa1.__proto__と見なすことができます。

今、A.prototype = {};と言うとき、この時点でオブジェクトa1は既に構築されており、このリンクを介してA.prototypeを指しています。

JavaScriptはガベージコレクション言語なので、A.prototypeを{}に設定するだけでは古いprotoytpeオブジェクトをクリーンアップしていないため、古いオブジェクトはまだ残っています。 console.log(a1.howCool());と言うと、howCoolは残っているオブジェクトにあります。

だから、あなたはこのようなあなたのLINE3を変更する場合:

// LINE3

console.log(a1.__proto__); 
a1.__proto__ = {}; 
console.log(a1.howCool()); 

あなたはラインでコンソールウィンドウで、その中の古いプロトタイプオブジェクトとhowCool()を参照することができるだろうconsole.log(a1.__proto__); ただし、a1.__proto__ = {};と設定すると、console.log(a1.howCool());はオブジェクトを見つけることができず、howCool()が見つからない(空のオブジェクトに設定されるため)。

したがって、A.prototypeを{}に設定すると、a.__proto__ = {}と同じ効果が得られません。

したがって、表示される出力。

希望します。

+0

'__proto__'を使用しないでください。非難され、間違った印象を作ります。標準の 'Object.getPrototypeOf'を使用してください。 – Bergi

+0

@Bergi確かに、私はそれを使用するつもりはありません。これは、OPが見ている行動の背後にある推論を説明することに過ぎない。私は彼に追加の詳細を混同したくない。コンソールウィンドウのa1オブジェクトでこのプロパティを表示する方が簡単です。 –

+0

それを除く*は実際のプロパティではないため、わかりにくいです。 – Bergi

関連する問題