JS的原型鏈
本文闡述了js中的prototype,constructor和proto之間的關(guān)系。
同時(shí)梳理了js如何實(shí)現(xiàn)繼承的。
屬性釋義
-
prototype
prototype是JS中除了通過(guò)bind()生成的函數(shù)外所有function都具有的屬性,其值為一個(gè)對(duì)象,對(duì)象里包含兩個(gè)
值(proto和constructor)。作用是存儲(chǔ)要共享的屬性和方法。 - _proto_([[Prototype]])
proto是JS中每個(gè)對(duì)象都有的屬性,其值指向了該對(duì)象構(gòu)造函數(shù)的prototype。 -
constructor
constructor即構(gòu)造函數(shù),構(gòu)造函數(shù)就是構(gòu)造函數(shù),其值為函數(shù)本身。
實(shí)例屬性與類屬性
- 類屬性是指綁定到prototype上的屬性,可以被所有通過(guò)該構(gòu)造函數(shù)創(chuàng)建的實(shí)例繼承。
- 實(shí)例屬性是指綁定到this上的屬性,可通過(guò)在構(gòu)造函數(shù)內(nèi)給對(duì)象init時(shí)綁定或者直接在
生成對(duì)象后綁定。其值是不可共享的。
屬性之間的關(guān)系
//定義一個(gè)構(gòu)造函數(shù)
var Foo = function(){}
此時(shí)[1] Foo.prototype = {constructor: Foo, __proto__:Object.prototype}
即:Foo.prototype.__proto__ === Object.prototype,
因?yàn)?Foo.prototype的值是個(gè)Object實(shí)例,
所以[3] {}.__proto__ = Object.prototype
console.log(Foo.prototype.__proto__ === Object.prototype
console.log(Foo.prototype.constructor === Foo)
var f1 = new Foo()
//此時(shí)[2] f1.__proto__ === Foo.prototype
console.log(f1.__proto__ === Foo.prototype)
Foo是我們自定義的構(gòu)造函數(shù),JS內(nèi)置的構(gòu)造函數(shù)也是同樣的如Object,這里的Object是個(gè)構(gòu)造函數(shù)
Object.prototype = {constructor: Object, __proto__: null}
console.log(Object.prototype.__proto__)
//null
為什么[4] Object.prototype.__proto__會(huì)是null呢?
Object.prototype 不是為 {} 嗎, {}.__proto__不應(yīng)該
是Object.prototype嗎?而且我們自定義的構(gòu)造函數(shù)就是這個(gè)樣子呀!
如果設(shè)置Object.prototype.__proto__ = Object.prototype 那么,當(dāng)查找一個(gè)不存在的屬性時(shí),JS
會(huì)從上級(jí)原型鏈去查這個(gè)屬性,便會(huì)出現(xiàn)死循環(huán),所以ES5規(guī)定Object.prototype.__proto__ = null
而且Object.prototype 指向的對(duì)象并不是繼承自Object,即它不是Object的實(shí)例。
The value of the [[Prototype]] internal property of the Object prototype object is null, the value of the [[Class]] internal property is "Object", and the initial value of the [[Extensible]] internal property is true.
上面提到JS內(nèi)置的構(gòu)造函數(shù)Object,在JS中函數(shù)也是一種對(duì)象,即也存在Object.__proto__ 那么它指向誰(shuí)呢?當(dāng)然是Function.prototype了,因?yàn)?br>
Function是js中所有function的構(gòu)造函數(shù),所以function Object(){}是Function的一個(gè)實(shí)例。
所以[7] Object.__proto__ === Function.prototype
console.log(Object.__proto__ === Function.prototype)
//true
JS中Function也是一個(gè)構(gòu)造函數(shù)。
所以[9] Function.prototype = {constructor: Function, __proto__: Object.prototype},
[10] Function.__proto__ = Function.prototype
至此便是一個(gè)完整的JS原型鏈。