首先咱們看一張經典的圖,是否是很懵逼。javascript
哈哈!不用慌,我當年看也是很懵逼的。並且不少作前端不少年的都不必定了解這個圖,因此若是你瞭解了,至少在JS領域,你的上限就會大大提升喲。前端
由於時間有限,本文我就帶你們分析其中一條線路。基本上一條線路通了,其餘的天然就走得通了。java
首先在分析以前,咱們要弄清楚一個概念。對象,函數以及原型之間的關係。首先咱們來談談的對象的問題,在JS中,任何事實存在的東西都是對象。包括函數也是一個對象。那麼咱們平時new出來的對象,看似是由函數實例出來的,可是,這實際上是一個假象,這也是習慣於JAVA,C++等基於類語言的一個區別就在這裏。函數
第一個概念咱們要了解,JS的全部對象不是說是構造函數實例化(也就是new)而來的。在JS中,構造函數這個概念仍是存在的,可是實例化這個概念在JS中並無的。那麼JS的對象哪裏的來的?重點就是在於一個叫作原型屬性的東西。也就說,JS對象實際上是產生與構造函數的原型屬性中的。prototype
可是對象並不等於構造函數的原型屬性,他們並非相等;對象
function fn(){} var obj = new fn(); obj === fn.prototype;//false
也就是說,他們並非一個對等關係。那麼是啥關係,這個關係叫作克隆,雖然沒有具體代碼去描述這個關係,可是JS仍是給咱們保留了一個屬性去維持這個中關係。叫作__proto__,其實在圖上咱們也能夠發現這個關係存在的。blog
好比,上圖new foo(),很明顯,這是一個實例的對象,構造函數是函數foo,那麼對象和構造函數之間有一個__proto__鏈接着。ip
其實經過代碼,咱們也能夠確認這個關係:原型鏈
function foo(){} new foo().__proto__ === foo.prototype;//true
這也就是爲何,咱們在構造函數原型屬性上的寫的方法和屬性咱們在實例化對象以後是能夠訪問到的緣由,就是這個__proto__起了很大的一個做用。原型
可是到如今爲止,原型鏈,鏈這個東西哪裏去了?
好了,咱們如今已經知道實例和構造函數以及構造函數原型屬性之間的關係了。那麼,構造函數的原型咱們能夠typeof一下,看看會發生什麼。
typeof foo.prototype;//object
那麼意思它也是一個對象,那麼它是對象,那麼他的構造函數是誰?這個對象來自與哪裏?咱們其實看到圖裏面,foo.prototype實際上是指向的是Object.prototype。而後咱們能夠試一試。
foo.__proto__.__proto__ ===Object.prototype;//true
這其實就很清楚的說明一點,也就是說函數foo的原型對象是產生與Object實例的原型,那麼這樣,實例,對象原型,object原型之間就有了一條鏈式關係了,包括最後Object的原型屬性也是往上連接的就是變成了null了。
其實咱們再typeof null的時候就可能會納悶,這旮旯怎麼會是對象了。其實它不單單是對象,也是JS整個體系的最上一級。全部JS對象都是由它一級一級克隆下來的,想不到把,哈哈!