JS做爲發展了多年了對象語言,支持繼承,和徹底面向對象語言不一樣的是,JS依賴原型鏈來實現對象的繼承。函數
首先JS的對象分兩大類,函數對象和普通對象,每一個對象均內置__proto__屬性,在不人爲賦值__proto__的前提下,普通__proto__屬性指向其構造函數的.prototype屬性,例如:spa
var test={};prototype
此時test.__proto__指向Object.prototype,Object爲原型鏈的頂端,一切對象都可追朔到Object.對象
function money(){};繼承
var test=new money();ci
此時test.__proto__指向money.prototype.原型鏈
普通對象沒有prototype屬性。(Object除外)原型
再來看函數對象:io
function money(){};console
此時money是一個函數對象,其__proto__指向Function.prototype
Function.prototype也是一個普通對象,又回到了上面所說的,因此Function.prototype中的__proto__屬性指向Object.prototype。
這裏只需記住一點,一切對象均有__proto__屬性,一切對象繼承鏈頂端都是Object對象,那麼Object.prototype.__proto__又指向哪裏呢?
console.log(Object.prototype.__proto__)
//null
即頂端的對象再也不繼承任何對象,他的父級是空。
既然知道了JS原型鏈,再一塊兒來了解實際項目中的應用
這裏咱們定義了一個函數對象
var father=funcion(){};
var son=new father();
var son1=new father();
這裏咱們得到了兩個普通對象son,son1
兩個普通對象的__proto__均指向father.prototype,由於他們都是由father函數對象構造出來的。
若是這時咱們須要爲son增長一個屬性,咱們能夠這麼寫
son.say=function(){alert(‘hello world!’)}
son.say();
//hello world!
固然沒問題,若是咱們須要son1也有一樣的屬性呢,son1.say=function(){alert(‘hello world!’)}
son1.say();
//hello world!
代碼沒有任何問題,運行良好。
若是咱們用father構造了不少對象,son1,son2.....son10000,這是咱們須要這些構造出來的對象都有這個屬性該怎麼辦!
father.prototype.say=function(){alert(‘hello world!’)}
var son1000=new father();
son1000.say();
//hello world!
咱們沒有爲son1000添加任何屬性方法,但它依然能夠正常運行。
來看原理:
JS約定在獲取對象內置屬性時,首先會去當前對象中尋找,若是找不到,則去.__proto__所指向的對象中去尋找,因爲.__proto__所指向的對象自己也有.__proto__屬性,因此若是沒有找到則繼續根據當前對象.__proto__所指向的對象去繼續尋找,在整個過程當中,若是找到則終止繼續向上查詢,不然一直會追蹤到Object.prototype,若是整條鏈上均沒有找到,那麼結果就是undefined!