一、理解原型
js創建的每個函數都有一個prototype屬性,這個屬性指向一個對象。這個對象用來存儲通過這個函數所創建的所有實例共有的屬性和方法, 這個對象稱為所有實例的原型對象。每個原型對象都包含一個constructor屬性,它指向prototype屬性所在的函數。
二、搜索對象屬性的過程
每當代碼讀取某個對象的某個屬性時,都會執行一次搜索,目標是具有給定名字的屬性。搜索首先從對象實例本身開始。如果在實例中找到了具有給定名字的屬性,則返回該屬性的值;如果沒有找到,則繼續搜索_proto_指針指向的原型對象,在原型對象中查找具有給定名字的屬性。如果在原型對象中找到了這個屬性,則返回該屬性的值。
通過實例只能訪問原型對象的值,不能修改原型對象的值。如果我們在實例中添加了一個屬性,而該屬性與實例原型中的一個屬性同名,那么就會在實例中創建該屬性,該屬性將屏蔽掉原型中的那個屬性。
三、使用原型實現繼承
1.繼承的含義
繼承是面向對象編程中的一個重要概念,通過繼承可以使子類的實例使用在父類中定義的屬性和方法。
2.實現繼承
在js中我們可以創建一個對象o,通過這個對象可以訪問父類中定義的所有屬性和方法,然后把這個對象作為子類實例的原型對象。 這樣的話子類實例就可以通過搜索原型來訪問父類中的所有屬性和方法。一般情況下可以通過創建父類對象的實例來創建對象o;舉例如下:
1 function Animal(){ 2 3 } 4 Animal.prototype.shout=function(word){ 5 console.log(word); 6 } 7 8 function Bird(){ 9 10 } 11 Bird.prototype=new Animal(); 12 //為原型添加constructor屬性; 13 Bird.prototype.constructor=Bird; 14 15 var bird=new Bird(); 16 bird.shout("gugugu...");
上例中shout屬性的查找過程:先查找bird實例,沒找的,再查找bird的原型對象,即Animal的實例,沒找到,接下來查找Animal實例的原型,找到。由於每一個實例都有一個原型,通過這種方式就會形成一條原型鏈,圖示如下:
四、封裝一個實現繼承的方法
1 function extend(subclass, superclass) { 2 "use strict"; 3 //創建一個對象作為子類的原型對象 4 function o() { this.constructor = subclass; } 5 //設置對象的原型為父類的原型,從而使對象可以訪問父類方法 6 o.prototype = superclass.prototype; 7 return (subclass.prototype = new o()); 8 };