在去了解原型鏈之前,一定要先搞清楚兩個概念,一個是prototype,一個__proto__。耐心往下看哦
1.prototype
首先什麼是prototype?prototype是函式的一個屬性,它是一個物件,裡面含有兩個屬性 constructor,__proto__,分別是什麼呢??如下圖,constructor是一個構造器,它指向自身,而__proto__指向的是物件
記住:一切物件的根源 - Object.prototype
2.__proto__
__proto__是物件(出去null)所擁有的一個屬性,它指向的構造這個函式的原型物件(prototype),取個栗子
function a(){}
console.log(a.__proto__ === Function.prototype) //true複製程式碼
應該會有人會問,Object的
console.log(Object.prototype.__proto__ === null) //true
複製程式碼
3.原型鏈
怎麼解釋原型鏈,其實需要靠大家去理解
寫一小段簡單的程式碼,在進行解釋
function Person(){}
let p1 = new Persion()複製程式碼
1.每個函式(通常指建構函式,如Person)都有一個屬性:prototype
2.prototype是一個物件, 裡面有constructor , __proto__ 隱式原型
3.建構函式的原型物件指向當前建構函式 Person.prototype.constructor === Person
4.例項物件的隱式原型指向建構函式的顯示原型
p1.__proto__ === Person.prototype
5.在建構函式顯示原型中新增的方法,所有的例項物件共享
6.訪問屬性和方法,是基於原型連進行訪問 在當前的例項物件去找--》建構函式的原型 ==》.... =》 Object的原型
光看這幾句話會很乾,可以看看下面的例子
4.簡單的原型鏈的題及其解釋
var F = function(){}
F.prototype.b = function (){
console.log('b()');}
Function.prototype.c = function () {
console.log('c()');}
Object.prototype.a = function () {
console.log('a()')
};
var f = new F();
F.a();
F.b();
F.c();
f.a();
f.b();
f.c(); 複製程式碼
這道題完全就是和原型相關,如果你能準確的說出答案,那麼原型和原型鏈的理解基本就是明白的了,做這道題的關鍵需要分清楚原型鏈的訪問(例項物件直接訪問建構函式的顯示原型的函式)
畫一張圖就能很清楚的看出答案,話不多少,看圖
看完圖之後,可以看出原型鏈分為兩條 - 一條是紅色,一條是綠色,原型鏈上的方法,例項物件都是可以訪問的
F.b(),報錯,訪問F的b方法,應該為F.prototype.b(),記住一句就是例項物件可以直接訪問建構函式顯示原型的方法
f.c(), 報錯,c並不是在f的原型鏈上面,而是在F的原型鏈上
5.Object和Function之間的關係
第一,萬事萬物皆物件
console.log(Function.prototype.__proto__ === Object.prototype) //true
console.log(Number.prototype.__proto__ === Object.prototype) //true複製程式碼
然後,js的所有類都是Function的例項,也是Object的派生類,Object物件直接繼承Function物件
console.log(Object.constructor === Funciton) //true
console.log(Object instanceof Function) //true
console.log(Function instanceof Object)//true
console.log(Object.__proto__ === Function.__proto__) //true
console.log(Object.__proto__ === Function.prototype); //true
console.log(Function.__proto__ === Function.prototype); //true複製程式碼
也就是說可以理解為物件其實也是由函式構造,Object其實也是個函式,而任何函式都是Function的例項物件(Object.__proto__ === Function.prototype),而函式自己構造了自己(Function.__proto__ === Function.prototype),也來看圖理解
但是,敲黑板,不要進入一個誤區,如果說一切物件都能訪問到Object的prototype裡面的方法,像hasOwnProperty,toString,valueOf,toLocaleString等等,那是不是物件都可以訪問到在函式原型的方法,答案是,no. 原因又回到了原型鏈,大家不要進入誤區,值得注意的是,原型鏈的指向,最後指向了Object.prototype而不是Object.__proto__,Object.prototype.__proto__ === null
所以原型鏈只需要要死死的記住二句話就行了,1.函式的例項物件的隱式原型(__proto__)指向的建構函式的原型物件(prototype),2.所有的最後都指向了物件的顯示原型(prototype)
哈哈,終於寫完了