看過很多相關文中,有通俗易懂的,也有晦澀難懂的,但是只要不是自己整理的始終都不會消耗成自己的知識儲備。建議都用自己的理解去整理,那樣思路是自己的,日后就算忘記了,看一眼也馬上可以記起來。
1、什么是原型對象prototype?
原型是一個對象,並且只有函數有prototype。
prototype對象中有一個constructor屬性,指向了這個函數本身。
function test () {} var fn = new test() // test.prototype就是fn的原型對象,可以理解通過new 將 fn 和 test.prototype建立連接(原型繼承) console.log(test.prototype.constructor === test) // true
2、什么是__proto__(隱式原型)?
_proto_實際上是某個實例對象的隱藏屬性, 任何對象都有__proto__,指向它所對應的構造函數的原型對象
我到這個地方就有點亂了,什么關系指來指去,為什么定義的字符串/number/true、false變量都有__proto__。一臉懵逼啊!!!到這里就要岔開話題了,先了解下另外一個知識點,
js的三大包裝對象Number()、String()、Boolean()
我們知道常用的 基本類型(原始類型):有 number、string、boolean、undefined、null
其中, number、string、boolean這三個類型比較特殊。在調用其某個方法時,JavaScript 引擎會自動將原始類型的值轉為包裝對象實例,也就是原始類型的“包裝對象”。可以調用各種包裝對象的屬性和方法,在使用后立刻銷毀實例。自動轉換生成的包裝對象是只讀的,無法修改。
let str = 'hello word' console.log(str.length)
// 訪問length屬性,但str本身不是對象,不能調用length屬性。
// javascript引擎自動將其轉為String包裝對象,在這個對象上調用length屬性。調用結束后,這個臨時對象就會被銷毀。
// number、boolean類型等同
復雜類型: array、function、object
復雜類型是由js內置對應的構造器實例而來,Array、Function、Object
回歸主題,__proto__指向它所對應的構造函數的原型對象
所以這里,第一步就很清晰了
let str = 'hello word' console.log(str.__proto__ === String.prototype) // true
let num = 1 console.log(num.__proto__ === Number.prototype) // true
let flag = true console.log(flag.__proto__ === Boolean.prototype) // true
function test () {} console.log(test.__proto__ === Function.prototype) // true
let arr = [] console.log(arr.__proto__ === Array.prototype) // true
let obj = {} console.log(obj.__proto__ === Object.prototype) // true
所有的構造器都是Function函數(構造器)的實例,所以以上所有構造器(String、Number、Boolean、Function、Array、Object)的__proto__,均指向Function.prototype
這里是不是感覺更加清晰了一點呢~ 出個題目
// 看看以下__proto__指向什么呢? console.log(Number.prototype.__proto__) let str = 'hello world' console.log(str.__proto__.__proto__)
解題
console.log(Number.prototype.__proto__) // Number.prototype 是個原型對象,故名思意,對象對象,對象是由Object函數構造而來。所以 Number.prototype.__proto__ === Object.prototype let str = 'hello world' console.log(str.__proto__.__proto__) // 第一步:str.__proto__ 指向其構造函數的原型對象,固str.__proto__ === String.prototype // 第二部:String.prototype.__proto__,是不是就是上一題,原型對象,對象由Object函數構造而來,所以 str.__proto__.__proto__ === Object.prototype
特比注意的是,所有 構造函數.prototype.__proto__ 都會指向Object.prototype 。唯獨Object.prototype.__proto__ === null 。記不住的話就記住一句話,對象生萬物,萬物皆對象。
3、什么是原型鏈?
以上對原型對象和__proto__有了一定的了解,那什么是原型鏈?
當訪問一個對象的某個屬性時,會先在這個對象本身的屬性上找,如果沒有找到,會去這個屬性的__proto__屬性上找,即這個構造函數的prototype,如果還沒找到,就會繼續在__proto__上查找,直到最后一層,找不到即為undefined。這樣一層一層往上找,彷佛是一條鏈子串起來,所以叫做原型鏈。
可以去找一些相關題目做個練習加深對原型和原型鏈的理解~