深刻理解JavaScript中的繼承:原型鏈篇

 

1、何爲原型鏈chrome

  原型是一個對象,當我調用一個對象的方法時,若是該方法沒有在對象裏面,就會從對象的原型去尋找。JavaScript就是經過層層的原型,造成原型鏈。函數

2、誰擁有原型測試

  任何對象均可以有原型,當咱們建立對象的時候,會自動爲對象添加一個屬性,這個屬性就是原型,咱們沒法訪問到他,但在firefox和chrome中能夠經過一個非標準的屬性__proto__(雙下劃線)來訪問到原型(或經過Object.getPrototypeOf來訪問)。firefox

3、理解原型鏈prototype

  咱們先從如下代碼入手對象

  var foo = {};繼承

  console.log(foo.toString());// [object Object]  
  console.log(foo.__proto__);// object { ...}  這裏指向Object.prototypeip

  foo裏面明明沒有toString方法,但我卻能調用,這就是原型鏈的做用。當我調用foo.toString時,因爲在裏面找不到toString方法,那麼我從__proto__屬性裏面去找,找到後並調用。上面的代碼中咱們就是從Object.prototype中找到了toString方法。你可能會很困惑,prototype是什麼?咱們不要被prototype所迷惑,他只是一個存放屬性的容器而已,你能夠以下這樣作來實現繼承(但儘可能不要這麼作)原型鏈

 

function Bar() {}get

Bar.test = {

  say: function () {

      console.log('say test');    

    } 

}

 

var foo = new Bar();

foo.say(); // 報錯

 

// 改變繼承的對象

 

foo.__proto__ = Bar.test;

foo.say() // say test

  在上面的代碼中咱們經過new的形式來建立一個對象,在new的過程當中對象會將__proto__指向函數的prototype,因爲prototype中是沒有say函數的,因此調用會報錯,可是以後咱們強行改變了繼承的對象,將foo的繼承對象改成Bar.test,因此咱們就能調用say函數了。

 

  我想你已經明白個大概了,prototype事實上並無什麼特殊的,硬要說有什麼特殊的話,他只是被JavaScript默認爲原型屬性的存放點而已,他本質上只是個對象,原型鏈的重點就在於__proto__,你能夠試着把__proto__看成橋樑,當我在對象內部找不到屬性時,我就會經過這座橋樑到對面的對象裏去尋找屬性,直到找到爲止或者對象裏沒有橋樑時才停下來。JavaScript就是經過這樣的方式來造成原型鏈,實現繼承的關係。

  最後說一下,__proto__只是方便咱們查看對象的原型而已,你們不要經過修改__proto__來實現繼承的關係,而是要用如構造函數之類的方式來實現繼承,這個我會放到之後的文章去說。

(ps:可能有動手能力強的同窗會本身去測試,發現__proto__裏面也有__proto__,一直循環下去,無窮無盡,但事實上你去獲取的時候你會發現Object.__proto__.__proto__.__proto__的值是null,也就是沒有原型。)

相關文章
相關標籤/搜索