涉及知識點:(1)原型的引入(2)構造函數、原型對象和實例對象之間的關係(3)__proto__和prototype的理解 直接舉例:在自定義構造函數創建對象時,因為創建的對象使用的不是同一個方法,所以創建對象越多,就會開闢大量空間造成記憶體浪費。 驗證:在<script>標簽中寫如下代碼,瀏覽器中打 ...
涉及知識點:(1)原型的引入(2)構造函數、原型對象和實例對象之間的關係(3)__proto__和prototype的理解
直接舉例:在自定義構造函數創建對象時,因為創建的對象使用的不是同一個方法,所以創建對象越多,就會開闢大量空間造成記憶體浪費。
驗證:在<script>標簽中寫如下代碼,瀏覽器中打開,按F12可以看到所創建的對象都擁有各自的方法。其中的console.dir(per);可以把這個對象的結構顯示出來。
而且將方法放在構造函數外部來指向同一個函數也不好,雖然可以使用相同方法但是在外部函數定義時容易引起變數命名衝突的問題,<script>中寫入代碼,驗證如下:
所以引入原型的概念,在<script>中寫入代碼,控制台看到對象的各自的方法是相同的(true),共用的,就不會開闢多餘空間造成記憶體浪費。
那麼這就有一個問題:實例對象中根本沒有eat方法,但是能夠使用,這是為什麼?要明白這個問題,首先需要知道一些知識。就是要知道__proto__和prototype之間的關係,以及構造函數、原型對象和實例對象三者之間的關係。先上圖再解釋!
1、在JS里,萬物皆對象。方法(Function)是對象,方法的原型(Function.prototype)是對象。
2、JS里所有的對象都有__proto__屬性,也可稱為隱式原型,指向構造該對象的構造函數的原型。保證了實例能夠訪問在構造函數原型中定義的屬性和方法。
3、只有函數function才具有prototype屬性。這個屬性是一個指針,指向一個對象,這個對象的用途就是包含所有實例共用的屬性和方法(我們把這個對象叫做原型對象)。原型對象也有一個屬性,叫做constructor,這個屬性包含了一個指針,指回原構造函數。
4、實例對象的__proto__和構造函數中的prototype相等--->true。又因為實例對象是通過構造函數來創建的,構造函數中有原型對象prototype,實例對象的__proto__指向了構造函數的原型對象prototype。對象.proto=構造器.prototype。
5、實例對象中有__proto__這個屬性,叫原型,也是一個對象,這個屬性是給瀏覽器使用,不是標準的屬性,__proto__也可以叫原型對象
構造函數中有prototype這個屬性,叫原型,也是一個對象,這個屬性是給程式員使用,是標準的屬性,prototype可以叫原型對象
接下來對上圖進行解析(重點):由Person.prototype.eat=function () 知道eat方法不在實例對象中,而是在構造函數的原型對象中,但是實例對象可以使用eat方法,是因為實例對象的原型__proto__指向了原型對象,原型對象中有eat方法,所以p1就可以使用eat方法而原型對象是在構造函數裡面的prototype屬性中。
以上內容屬於個人學習總結,便於以後的回憶複習,有誤之處,還望指正。