原型是什么?
在Java中,對象會從類中繼承屬性,方法等,但JavaScript中并沒有類的概念,JavaScript中的對象從原型對象中繼承屬性,方法。(雖然在ES6中引入class關(guān)鍵字,但本質(zhì)上是一種‘語法糖’,并不是真正意義上的類概念)。
一個‘神奇’的現(xiàn)象
我們先定義一個構(gòu)造器(函數(shù)):
function People(a,b,c){
this.height = a;
this.weight = b;
this.age = c;
}
對于構(gòu)造器,訪問屬性prototype可以獲得它的原型對象:
console.log(People.prototype);
在瀏覽器控制臺中會顯示:

這就是它的原型對象。
如果點開constructor,會發(fā)現(xiàn)里面有里面包含proto屬性(并不是上圖中的proto,而是constructor中的proto),再點開proto會出現(xiàn)‘套娃’的情況:

又出現(xiàn)了constructor,再點開constructor里面還有proto屬性,這么一直點下去是無窮無盡的……
其中的proto屬性,指向一個對象的構(gòu)造函數(shù)的原型。
其實歸根結(jié)底,原因就一個式子:
構(gòu)造器(函數(shù))的原型對象(prototype)的構(gòu)造器(constructor)就是函數(shù)本身
結(jié)合上面的構(gòu)造函數(shù)就是:People == People.prototype.constructor
(也就是說一直點開下拉菜單相當(dāng)于不停輪流訪問prototype和constructor屬性,所以是無窮無盡的)
原型對象
說回原型,原型是個很抽象的概念,因為我們并不能看到它。當(dāng)定義了一個構(gòu)造器的時候,就會產(chǎn)生一個原型對象。這個構(gòu)造器所構(gòu)造的對象,都會從原型對象中繼承到屬性,方法等,我們定義一個小明‘xiaoming’對象,并打印出來:
var xiaoming = new People(170,60,18);
console.log(xiaoming);
在控制臺可以看到:

檢查小明對象的proto屬性,也就是小明對象的構(gòu)造器的原型對象,我們會發(fā)現(xiàn)它實際上就是上面我們看過的People構(gòu)造器的原型對象(People.prototype)。
那么什么是原型鏈呢?
其實理解了原型,就很好理解原型鏈了,我們發(fā)現(xiàn)小明對象繼承自People構(gòu)造器的原型對象,而People構(gòu)造器的原型對象又是從哪繼承的呢?上圖中最后一行proto,也就是
__proto__:Object
它就是JavaScript中的object(對象)的構(gòu)造函數(shù),點開它會發(fā)現(xiàn)它不再擁有proto屬性了,也就是它的proto屬性是null,這就說明尋找構(gòu)造函數(shù)到頭了,這就是所謂的原型鏈的終點。
事實上,隨便定義一個對象:
var xiaohei = {
height:180,
weight:80,
age:20
}
然后去控制臺打印出來:
console.log(xiaohei);
會顯示:

它并沒有一個構(gòu)造函數(shù),它的原型對象的構(gòu)造函數(shù)就是object構(gòu)造函數(shù),事實上在JavaScript中不管什么對象,只要順著它的proto屬性往上尋找,就必然會回到object構(gòu)造函數(shù),也就是說JavaScript中任何對象都是object的實例。這就是原型鏈。
這篇文章比我說的牛批多了,沒看明白的去看這個吧:(得,講了半天不如給個鏈接)
https://juejin.im/post/5d713de26fb9a06ad3474c15
文章里面可能有錯誤,如果有讀者看到希望能指出