關(guān)于原型鏈,__proto__和prototype庭敦,繼承

ES6關(guān)于構(gòu)造函數(shù)和繼承有了新的語法疼进,但先分析之前的寫法,有助于理解原理

1.原型鏈

javascript沒有像Java秧廉、C#類的概念伞广,要實現(xiàn)繼承只能是通過“原型(prototype)”這條鏈子將要繼承的對象鏈接起來

//對象
var o={}
o.__proto__===Object.prototype//true
//數(shù)組
var arr=[1,2]
arr.__proto__===Array.prototype //true
Array.prototype.__proto__===Object.prototype //true
Object.prototype.__proto__===null //true
//函數(shù)
function f(){}
f.__proto__===Function.prototype//true
Function.prototype.__proto__===Object.prototype//true

說實話一直困惑__proto__prototype這倆啥關(guān)系拣帽,通過上面的代碼就再清晰不過了__proto__指向了所繼承的父原型,prototype指向自己的原型嚼锄,所以通過修改__proto__可以改變所繼承的原型减拭,但__proto__ 并不是語言本身的特性,這是各大廠商具體實現(xiàn)時添加的私有屬性区丑,雖然目前很多現(xiàn)代瀏覽器的 JS 引擎中都提供了這個私有屬性拧粪,但依舊不建議在生產(chǎn)中使用該屬性,避免對環(huán)境產(chǎn)生依賴刊苍。生產(chǎn)環(huán)境中既们,我們可以使用 Object.getPrototypeOf方法來獲取實例對象的原型,然后再來為原型添加方法/屬性正什。

2.構(gòu)造函數(shù)

function Person(name,age){
  this.name=name
  this.age=age
  this.sayName=function(){
    alert(this.name)
  }
}
Person.prototype.constructor===Person//true

以上是個構(gòu)造函數(shù)啥纸,我一直覺得就是個函數(shù),但其實它返回的是個對象婴氮,用new關(guān)鍵字構(gòu)造一個對象斯棒。并且在自己的prototype上將constructor屬性指向了自己

var person1=new Person('張三',27)
var person2=new Person('李四',18)
person1.constructor===Person//true
person1.__proto__===Person.prototype//true
person2.__proto__===Person.prototype//true
person1.sayName===person2.sayName//false 這不是我們想要的

每個實例的屬性需要不一樣,因為每個人的名字不一樣主经,但是sayName需要共用荣暮,可以把需要共用的屬性或方法放在prototype上,

Person.prototype.sayName2=function(){
  alert(this.name)
}
person1.sayName2===person2.sayName2//true

現(xiàn)在Person上其實有2個屬性罩驻,一個是默認生成的constructor穗酥,另一個是sayName2,所以又可以用以下的寫法解釋

Person.prototype={
  constructor:Person,
  sayName2:function(){
    alert(this.name)
  }
}

接下來對比以下ES6的新語法class

class Person{
  constructor(name,age){//放在構(gòu)造器里面的是 不公用的
    this.name=name
    this.age=age
    this.sayName=function(){
      alert(this.name)
    }
  }
 //放在構(gòu)造器外面的是公用的
  sayName2(){
    alert(this.name)
  }
}

咋樣惠遏,就感覺是把之前的寫法合并起來了

3.繼承

//父構(gòu)造函數(shù)
function SuperType(name){
  this.name=name
}
SuperType.prototype.sayName=function(){
  alert(this.name)
}
//子構(gòu)造函數(shù)
function SubType(name,age){
  SuperType.call(this,name)
  this.age=age
}
var sub=new SubType('張三',12)
sub.name//"張三"
sub.sayName//undefined
sub.__proto__===SubType.prototype//true
SubType.prototype.__proto__===SuperType.prototype//false

先用call方法繼承構(gòu)造器里的屬性砾跃,此時的關(guān)系為,sub——>SubType——>Object节吮,要實現(xiàn)繼承要把SubType.prototype.__proto__===SuperType.prototype 你可能想這么寫 SubType.prototype = SuperType.prototype抽高,但這樣是不行的,他們倆公用一個原型的話透绩,SubType就沒有存在的意義了翘骂,我們可以用下面的代碼

function F(){}//先創(chuàng)建了一個臨時性的構(gòu)造函數(shù)
F.prototype = SuperType.prototype;//將父原型作為臨時構(gòu)造函數(shù)的原型
var prototype=new F()//這邊也可以直接用new SuperType(),但這樣加上上面的call方法會導(dǎo)致2次調(diào)用SuperType
prototype.contructor=SubType
SubType.prototype=prototype//然后將臨時構(gòu)造函數(shù)的實例作為子構(gòu)造函數(shù)的原型
SubType.prototype.__proto__===SuperType.prototype//true

下面來看看ES6繼承的寫法

class SuperType{
  constructor(name){
    this.name=name
  }
  sayName(){
    alert(this.name)
  }
}
class SubType extends SuperType{
  constructor(name,age){
    super(name)//必須調(diào)用下父類
    this.age=age
  }
  sayAge(){
    alert(this.age)
  }
}
var sub=new SubType('張三',12)
sub.__proto__===SubType.prototype//true
SubType.prototype.__proto__===SuperType.prototype//true

注意這邊會多一個聯(lián)系帚豪,這個是ES6特有的

SubType.__proto__===SuperType//true

這樣的結(jié)果是因為碳竟,類的繼承是按照下面的模式實現(xiàn)的。

class SuperType {
}
class SubType {
}
// B 的實例繼承 A 的實例  B.prototype.__proto__=A.prototype
Object.setPrototypeOf(SubType.prototype, SuperType.prototype);
// B 繼承 A 的靜態(tài)屬性  B.__proto__=A
Object.setPrototypeOf(SubType , SuperType );

這兩條繼承鏈狸臣,可以這樣理解:作為一個對象莹桅,子類(SubType)的原型(__proto__屬性)是父類(SuperType);作為一個構(gòu)造函數(shù)固棚,子類(SubType)的原型對象(prototype屬性)是父類的原型對象(prototype屬性)的實例统翩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仙蚜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厂汗,更是在濱河造成了極大的恐慌委粉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娶桦,死亡現(xiàn)場離奇詭異贾节,居然都是意外死亡,警方通過查閱死者的電腦和手機衷畦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門栗涂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祈争,你說我怎么就攤上這事斤程。” “怎么了菩混?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵忿墅,是天一觀的道長。 經(jīng)常有香客問我沮峡,道長疚脐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任邢疙,我火速辦了婚禮棍弄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疟游。我一直安慰自己呼畸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布乡摹。 她就那樣靜靜地躺著役耕,像睡著了一般采转。 火紅的嫁衣襯著肌膚如雪聪廉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天故慈,我揣著相機與錄音板熊,去河邊找鬼。 笑死察绷,一個胖子當(dāng)著我的面吹牛干签,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拆撼,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼容劳,長吁一口氣:“原來是場噩夢啊……” “哼喘沿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竭贩,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蚜印,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后留量,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窄赋,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年楼熄,在試婚紗的時候發(fā)現(xiàn)自己被綠了忆绰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡可岂,死狀恐怖错敢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缕粹,我是刑警寧澤伐债,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站致开,受9級特大地震影響峰锁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜双戳,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一虹蒋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧飒货,春花似錦魄衅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扣墩,卻和暖如春哲银,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呻惕。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工荆责, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亚脆。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓做院,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子键耕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348