6 回答

TA貢獻1895條經(jīng)驗 獲得超3個贊
哪里有矛盾? 繼續(xù)new b2出來的時候 b2 和 b的原型就是同一個對象了
Javascript中 var a = new A();
執(zhí)行完畢后,a和A就不再有任何的強綁定關(guān)系了,只有a.__proto__ === A.prototype
這個弱關(guān)系(而且還不一定成立!),你覆蓋掉了A.prototype
之后,自然a和A就不再有任何關(guān)系
var a = new A()
大致等價于下面的代碼
var a = (function() {
var context = Object.create(A.prototype);
var ret = A.call(context);
return ret !== null && typeof ret === 'object' ? ret : context;
})()

TA貢獻1847條經(jīng)驗 獲得超7個贊
假設(shè)有這樣的代碼:
function Test() {}
Test.prototype = {x: 1};
var a = new Test();
Test.prototype = {y: 2};
var b = new Test();
console.log(a.x); // 1
console.log(b.y); // 2
為什么a.__proto__沒跟著變?
首先,要了解清楚,a與b共享的只是Constructor.prototype的指向,而不是內(nèi)存,也就是每次new一個Constructor的時候,js都會new一個object,假設(shè)為ref,然后把ref的__proto__指向Constructor.prototype,這是每次創(chuàng)建一個實例都需要經(jīng)過的步驟,如果你在new之前改變prototype,ref.__proto__指向的將是不同的東西!
為什么a與b共享的proto引用不是同一塊內(nèi)存?
原因就是你把prototype指向了一個新的對象,破壞了引用。(指向了一個空對象,這會重新分配內(nèi)存,原有內(nèi)存空間還在,只不過現(xiàn)在不能通過Test.prototype來訪問而已)
類似的還有函數(shù)形參等情況:
function test(obj) {
// case 1:
// 在函數(shù)里面重新賦值了,obj指向了新的內(nèi)存空間,不再與temp有關(guān)聯(lián)
obj = {x: 1};
// case 2:
// 這里不重新分配內(nèi)存空間,只是為obj添加屬性的話,就會同時更新外部的temp對象
// obj.y = 3;
console.log(obj);
}
var temp = {y: 2};
test(temp);
// 如果test函數(shù)中沒有破壞temp引用的話,temp就不會受到影響
console.log(temp);
更經(jīng)典的還有nodejs的exports與module.exports。

TA貢獻1995條經(jīng)驗 獲得超2個贊
一樓答案的例子已經(jīng)可以說明這個現(xiàn)象的原因了,我這里補充一下。
理解這個現(xiàn)象,首先要了解JS里面new
操作符執(zhí)行的幾個動作,也就是當new Foo()
執(zhí)行的時候發(fā)生了什么事情,我這里簡單概括一下:
首先創(chuàng)建一個空對象,這個空對象的類型是
Foo
,并且空對象的隱式屬性__proto__
指向了Foo.prototype
所引用的對象;調(diào)用構(gòu)造函數(shù),進入上下文,執(zhí)行上下文的
thisValue
,也就是this
的值指向剛才創(chuàng)建的對象,然后函數(shù)代碼執(zhí)行;隱式返回剛才創(chuàng)建的對象(如果函數(shù)里面沒有顯式返回值得話);
理解了這個過程之后,題主的現(xiàn)象就很容易解釋了,當你創(chuàng)建實例a的時候a.__proto__
指向了Foo.prototype
引用的對象Foo {}
,當你給Foo.prototype
賦值為{}
的時候,Foo.prototype
就指向了你創(chuàng)建的這個空對象,原理類似于:
var foo = {x: 10},
bar = {y: 10};
var w = foo,
z = w,
w = bar;
console.log(b); // foo {x: 10}
Foo的實例a相當于例子中的z(可能有點繞),例子中w指向了另外的對象,但是z還是指向原來的對象,就像你的Foo.prototype指向了另外一個對象,但是a.__proto__卻還是指向原來的那個對象。
這時候當你再次執(zhí)行var b = new Foo()時,還是執(zhí)行上述的過程,b.__proto__指向了Foo.prototype引用的對象,也就是你賦值的那個對象,明顯這個對象和a.__proto__引用的不是一個對象。
還有就是你提到的
實例共享prototype
這句話有點斷章取義了,而且現(xiàn)在很多技術(shù)用語不是很嚴謹,更不能像記口訣一樣去學習知識,我們需要了解他的本質(zhì)過程。
希望我的回答對你有幫助!

TA貢獻1752條經(jīng)驗 獲得超4個贊
添加回答
舉報