什麼是建構函式?
建構函式本身就是一個函式,與普通函式沒有任何區別,不過為了規範一般將其首字母大寫。建構函式和普通函式的區別在於,建構函式用於使用new操作符生成例項,普通函式用來呼叫以實現某種功能。
什麼是原型?
每個函式都有一個prototype屬性,prototype屬性中的constructor屬性又指向函式自身。
什麼是原型鏈?
引用高程3的描述:每個建構函式都有一個原型物件,原型物件都包含一個指向建構函式的指標,而例項都包含一個指向原型 物件的內部指標。那麼,假如我們讓原型物件等於另一個型別的例項,結果會怎麼樣呢?顯然,此時的 原型物件將包含一個指向另一個原型的指標,相應地,另一個原型中也包含著一個指向另一個建構函式 的指標。假如另一個原型又是另一個型別的例項,那麼上述關係依然成立,如此層層遞進,就構成了實 例與原型的鏈條。這就是所謂原型鏈的基本概念。
如果你還沒理解建構函式和原型的關係,看完對於上面這段話,很可能更加暈了,所以下面我將用我的理解來描述建構函式和例項之間的關係,以及原型鏈到底是什麼。
function Person(name){
this.name = name;
};
let xm = new Person('小明');
xm.__proto__ === Person.prototype // true
xm.__proto__.constructor === Person // true
Person.prototype.constructor === Person // true複製程式碼
Person為建構函式,xm是通過new Person()得到的例項,其對應關係如下圖:
而如果我們這裡的Person.prototype同時又是另一個foo建構函式的例項呢?Person.prototype可以從foo.prototype繼承屬性和方法,xm又可以從Person.prototype繼承屬性和方法,由此得出以下結論:
每個物件都擁有一個原型物件,通過__proto__指標指向上一個原型 ,並從中繼承方法和屬性,同時原型物件也可能擁有原型,這樣一層一層查詢,最後指向Object.prototype,接著Object.prototype.__proto__ = null,物件之間的這種關係就是原型鏈。
那麼如上程式碼的原型鏈關係圖如下:
那如果加上Function物件又是什麼樣的呢?上圖:
上圖有一個讓人疑惑的點就是為什麼Function.__proto__ === Function.prototype?
我比較認同的一種觀點是:Function作為一個內建物件,是執行前就存在的東西,所以不會存在說Function自己建立自己,而同Function一起被建立的還有Function.prototype和Object.prototype,並通過__proto__將兩者聯絡起來,而為了和其他物件保持一致性,將Function.__proto__指向Function.prototype。
總結:
Object是所有物件的祖先,所有物件都可以通過__proto__找到Ojbect.prototype;
Function是所有函式的祖先,所有函式都可以通過__proto__找到Function.prototype;
每一個例項通過__proto__指向建構函式的原型,而建構函式的原型又通過__proto__指向建構函式的原型的原型,如此一層一層連結的關係,就是原型鏈。
如果有錯誤或者不嚴謹的地方,請給予指正,十分感謝!