解決原型鏈的引用型別值問題 組合繼承

2022-08-09 02:27:11 字數 2419 閱讀 7731

首先宣告乙個概念:我們雖然可以通過例項訪問儲存在原型中的值,但卻不能通過例項重寫原型中的值。如果我們在例項中給乙個屬性賦值,而且該屬性與原型中的乙個屬性同名,那我們就在例項中建立該屬性,該屬性會遮蔽原型中的那個屬性。

但是,雖然不能重寫原型中的值,如果原型中包含有引用型別(陣列,物件)的值的話,我們可以通過引用來修改原型中的值。

function

cat();

cat.prototype.type="animal";

cat.prototype.friends=['kitty','cookie'];

cat.prototype.speak=function

()var cat1=new

cat();

var cat2=new

cat();

console.log(cat2.friends);

console.log(cat1.type);

console.log(cat2.type);

cat1.speak();

cat2.speak();

原型中有乙個共享的陣列屬性friends,每乙個繼承它的例項都可以對它進行修改。顯然,每只貓咪都有應該自己的friends,而且不應該決定其他貓咪該有什麼friends。好吧,為了貓咪們能夠和諧相處,我們做一點點的改進。

//最常用的建立自定義型別的方法

function

cat();

cat.prototype.type="animal";

cat.prototype.speak=function

()var cat1=new

cat();

var cat2=new

cat();

console.log(cat2.friends);

console.log(cat1.type);

console.log(cat2.type);

cat1.speak();

cat2.speak();

建構函式為每只貓咪建立自己的friends屬性,也就是說,把需要共享的屬性和方法放在prototype裡,而例項自己獨立的屬性,則放在建構函式裡。

在原型鏈中,由於例項是另乙個例項的原型物件這樣的關係,我們即使把獨立屬性放在建構函式裡,這個屬性最終還是會成為另乙個例項的原型裡的屬性,上面的問題又重演了,怎麼辦。先舉個原型鏈的例子

function

sub();

function

super()

sub.prototype=new

father();

super.prototype.species="human";

var instance1=new

sub();

var instance2=new

sub();

instance1.friends.push('danyan');

console.log(instance1.friends);//['tom','jack','danyan']

console.log(instance2.friends);//['tom','jack','danyan']

super的獨立屬性被寫在建構函式裡了,它的例項都將擁有不同的friends屬性,但是,他的例項成了sub的原型,sub的例項,又將共享friends屬性,怎麼破。

分析一下,我們的目的是要sub繼承super,而且super中引用型別的屬性不被sub的例項共享。我們能不能像解決貓咪的問題那樣,把這個引用型別的應該被獨立出來的屬性,放在sub的建構函式裡,讓sub的例項們各自生成自己的這個屬性。答案,yes

//最常用的繼承模式

function

sub();

function

super()

sub.prototype=new

father();

super.prototype.species="human";

var instance1=new

sub();

var instance2=new

sub();

instance1.friends.push('danyan');

console.log(instance1.friends);//['tom','jack','danyan']

console.log(instance2.friends);//['tom','tack']

如此一來,在呼叫sub生成例項時,執行了super函式(super在這裡被當成乙個普通的函式),為例項生成了各自的friends屬性,遮蔽了sub的原型即super的例項中的friends屬性。這種方法被稱為組合繼承。組合了經典繼承(像sub那樣借用super)和原型鏈繼承。

引用型別改變值的問題

var arr1 marry split var arr2 arr1.reverse var arr3 blues split arr2.push arr3 console.log arr1 y r r a m b l u e s console.log arr2 y r r a m b l u e...

原型鏈二 Function的原型鏈問題

要理解function的原型鏈的問題 首先深入理解 proto proto 的含義是例項物件指向例項原型 例項的原型物件就是建構函式.prototype 例如function person var person new person console.log person.proto person.p...

值型別和引用型別的傳參問題

關於值型別和引用型別已經寫了兩篇部落格,之前大多都是理論階段,今兒就舉個栗子來看看他們兩種資料型別在傳遞引數方面到底有什麼不同的地方。今天的開場白還真的挺開門見山的哈 首先建立乙個person的類,有姓名 年齡 樣貌三個屬性 public class person public int age pu...