在JavaScript中,每個函數都有一個對象屬性(prototype),其指向另外一個對象。函數
爲什麼要設計prototype對象屬性?
JavaScript語言在設計時,其設計師不想將這門語言設計的過爲複雜,不想提升語言學習門檻,所以沒有引入類。可是其借鑑了new關鍵字,經過new關鍵字加構造函數的方式建立實例對象。若是隻有構造函數,那麼怎麼實現多個實例對象之間共享屬性和方法呢?爲了實現共享,設計師爲構造函數添加了prototype屬性,該屬性指向一個對象,全部實例之間共享的屬性和方法就放在這個對象上,不須要共享的屬性和方法就放在構造函數裏面,實例對象在建立完成以後,將自動引入prototype對象的屬性和方法。學習
function Person(name) { this.name = name } // 原型上添加一個共享方法 Person.prototype.say = function () { console.log(`my name is ${this.name}`) } let zs = new Person('zhangsan') // 實例對象能夠訪問原型上的共享方法 zs.say()
在原型中咱們得知,全部的構造函數都有一個prototype屬性,由此構造函數建立的實例對象都能自動獲取prototype上面共享的屬性和方法。那麼實例對象是如何獲取的?實例對象都有實例對象和原型之間的一種連接,也就叫原型鏈。this
function Person(name) { this.name = name } Person.prototype.say = function () { console.log(`my name is ${this.name}`) } let zs = new Person('zhangsan') // 實例對象proto屬性指向構造函數的原型 console.log(zs.__proto__ === Person.prototype) // true
因爲原型也是一個對象,能夠看做是Object的一個實例,所以,其__proto__屬性指向Object的原型。prototype
console.log(Person.prototype.__proto__ === Object.prototype) // true
因爲全部function都是由Fucntion生成的,也就是全部的函數能夠看做是Function的實例對象,所以函數的__proto__指向Function的原型。設計
console.log(Person.__proto__ === Function.prototype) // true
在每一個函數的原型prototype中都有constructor屬性,它保存了對函數的引用。code
console.log(Person.prototype.constructor === Person) // 因爲constructor保存了一個引用,所以能夠用其實例化一個對象 let lisi = new Person.prototype.constructor('lisi') lisi.say()