咱們好多常常會被問道JavaScript原型和原型鏈的概念,還有關於繼承,new操做符相關的概念。本文就專門整理了原型和原型鏈的概念,關於對象繼承咱們後邊進行介紹。本文包含對應的示例代碼和腦圖。若有奇異,歡迎指正!git
咱們先使用構造函數的方式聲明一個對象:函數
function Person() {} let person = new Person() person.name = '小紅' console.log(person.name) // 小紅
在上面的代碼中。Person是構造函數, person是經過new方式建立的實例對象。
如今開始進入一個環節post
prototype,constructor,__proto__是咱們常常見到的幾個概念,可是他們之間的關係具體是什麼樣的呢,讓咱們逐步開始瞭解。spa
每一個函數都有 prototype 屬性,除了 Function.prototype.bind(),該屬性指向原型, prototype: 指向實例對象的原型對象
prototype
function Person() {} Person.prototype.name = '小紅' let person = new Person() console.log(person.name) // 小紅
Person這個函數有聲明prototype屬性,那麼這個值指向的究竟是哪兒,是原型對象嗎?code
其實prototype指向的是,調用當前構造函數建立實例對象的原型,也就是person的原型。對象
那麼原型究竟是什麼呢?其實原型能夠理解爲,一個JavaScript對象(null除外)在建立的時候會關聯另一個對象,這個被關聯的對象就是咱們說的原型對象,實例對象會在建立的時候,從原型對象繼承一些屬性或者方法。
繼承
對應的關係圖以下:
ip
prototype講解了構造函數和原型對象之間的關係,那麼實例對象和原型對象之間的關係又是怎麼樣的呢?下面講解。每一個JavaScript對象(null除外),都會有個__proto__的屬性,這個屬性指向的就是原型對象
function Person() {} let person = new Person() console.log(person.__proto__ === Person.prototype) // true // ES5 經過實例對象獲取原型對象的方法 console.log(Object.getPrototypeOf(person) === Person.prototype) // true
由此咱們上面的管理系圖譜能夠補充爲:
上面講解了原型對象和構造函數,實例對象之間的關係,那麼反過來獲取原型對象和實例對象的構造函數是否是能獲取到呢??constructor就能作到這一點。constructor: 指向該原型對象對應的構造函數
function Person() {} let person = new Person() // 原型對象的構造函數 console.log(Person.prototype.constructor === Person) // true // 實例對象的構造函數 console.log(person.constructor === Person) // true // 實例對象自己是否含有constructor屬性 console.log(person.hasOwnProperty('constructor')) // false 注意: person.constructor 中其實是沒有constructor屬性的,這是從person的原型中獲取到的constructor屬性纔有了 person.constructor === Person。經過
關係圖能夠補充爲:
當咱們讀取一個對象的屬性是,若是實例對象中能找到,就會返回實例對象對應的value,若是沒有找到,就會站到實例對象的原型對象中,查看有無此值,有則返回,沒有的話,繼續查找原型的原型對象上有無此值。一直會查到頂層爲止。
function Person() {} Person.prototype.name = '小紅' let person1 = new Person() let person2 = new Person() person2.name = '小明' console.log(person1.name) //小紅 console.log(person2.name) //小明
那麼原型的原型執行的是什麼呢?
實際上,原型的原型也是一個實例對象,是經過Object的構造函數生成的,所以,原型的原型也能經過__proto__獲取其對應的原型對象的屬性。
function Person() {} Object.prototype.name = 'sunny' let person1 = new Person() let person2 = new Person() console.log(person1.name) //sunny console.log(person2.name) //sunny
對應的關係圖以下:
console.log(Object.prototype.__proto__ === null) // true
Object.prototype的原型爲null, null表明的意思是沒有對象,爲空。換句話的意思就是說,沒有原型對象了,這也就是查找的頂層對象了。
整個的關係圖咱們梳理爲:
關係圖中,紅色的線其實就是咱們平時說的原型鏈
了
console.log(Person.__proto__ === Function.prototype) //true console.log(Object.__proto__ === Function.prototype) //true
console.log(Function.prototype.constructor === Function) // true console.log(Person.constructor === Function) //true console.log(Person.hasOwnProperty('constructor')) //false console.log(Object.constructor === Function) //true console.log(Object.hasOwnProperty('constructor')) //false
console.log(Function.prototype === Function.__proto__) // true console.log(Function.prototype === Function.prototype) //true
console.log(Function.prototype.__proto__ === Object.prototype); //true
把這些所有總結完,以後咱們的關係圖,就變成了下面這個樣子:
JavaScript深刻之從原型到原型鏈