原型鏈?zhǔn)荍avaScript中比較重要的一個(gè)概念嚼锄,也是JavaScript中實(shí)現(xiàn)繼承的主要手段蔽豺。
原型鏈?zhǔn)鞘裁辞螅恳靼走@個(gè)概念,首先要明白修陡,原型是什么沧侥。
原型,就我個(gè)人而言魄鸦,就像我們的姓氏一樣(這個(gè)比喻不太恰當(dāng)),天地初開旺罢,世界大同绢记,我們?nèi)耍ɑ悾┒际峭环N姓氏(基類的原型),我們都從人這個(gè)基類下繼承了姓氏這么一個(gè)屬性蠢熄,當(dāng)然,你也可以特立獨(dú)行的去改姓签孔,自立門派砾跃,行走江湖(你的后代如果不改姓节吮,那么將會(huì)全部都跟你姓,這個(gè)沒(méi)得跑)透绩,但是并不會(huì)影響到其他人。
值得一提的是碳竟,遍歷原型的屬性是從自身的原型開始往祖先遍歷的狸臣,一直到找到該屬性為止,如果找不到烛亦,返回undefine,所以可以通過(guò)重寫父類方法‘覆蓋’父類的原型方法铐达,這就是為什么Array繼承了Object的toString()方法檬果,但Array.prototype.toString和Object.prototype.toString不一樣的原因瓮孙,Arrary自己重寫了toString()方法选脊。
可以通過(guò)hasOwnProperty這個(gè)方法來(lái)判斷該屬性是否是自身的屬性而非繼承,如果是自身偏灿,返回true角寸。
而原型鏈又是什么呢?就像族譜中的族譜線一樣扁藕。表達(dá)那種微妙的繼承關(guān)系的線,通過(guò)這種線邢疙,你就可以追根溯源,找到你的祖先疟游。(當(dāng)然,JS理論上是沒(méi)有多繼承的(其實(shí)也可以)蛮原,而族譜大多是多繼承另绩,請(qǐng)無(wú)視掉這一點(diǎn)。有那種微妙的繼承關(guān)系的感覺(jué)就行了)
道理雖然是這樣笋籽,感覺(jué)也說(shuō)得過(guò)去。但是车海,畢竟JavaScript對(duì)象不是人笛园,(人可以說(shuō)每一個(gè)都是實(shí)例侍芝,但是JavaScript對(duì)象不行吧)。
每當(dāng)我們聲明一個(gè)function的時(shí)候竭贩,JavaScript都會(huì)自動(dòng)給這個(gè)function添加一個(gè)prototype(原型)這么一個(gè)屬性,而prototype的value其實(shí)就是很多屬性的集合,值得一提的是哟冬,prototype里面有一個(gè)constructor(構(gòu)造函數(shù))這么一個(gè)屬性,顧名思義可岂,這個(gè)屬性是指向function本身的翰灾,或者說(shuō),是指向這個(gè)原型所對(duì)應(yīng)的的function本身纸淮,可以通過(guò)這個(gè)屬性來(lái)判斷其構(gòu)造函數(shù)是什么。
當(dāng)我們要實(shí)現(xiàn)繼承的時(shí)候绘面,一般是將父類的實(shí)例賦值給子類的原型,如 SubType.prototype = new SupType();這樣揭璃,子類的原型就有了父類的所有屬性,值得注意的是歼秽,如果我們創(chuàng)建了子類的實(shí)例情组,在調(diào)用子類的constructor屬性的時(shí)候,會(huì)發(fā)現(xiàn)呻惕,這時(shí)返回的是父類的構(gòu)造函數(shù),如var a = new SubType(); console.log(a.constructor);會(huì)返回function SupType(){}(所以我們需要手動(dòng)修正做院,在繼承之后加上如下操作:SubType.prototype.constructor = SubType濒持。)當(dāng)我們一層一層的繼承的時(shí)候,這種實(shí)例與原型之間的這種關(guān)系柑营,就構(gòu)成了我們所說(shuō)的原型鏈。