JavaScript是基於原型的物件導向語言,沒有類的概念,我們先來說說原型prototype。
每個對象都有原型,原型是一種對象,修改對象的原型,可以影響所有由本對象派生的對象,但是如果僅僅修改本對象,並不會影響已經建立的執行個體的原型。因為每個對象和原型都有一個原型,對象的原型指向對象的父原型,而父原型又指向父原型的父原型,這種通過原型層層串連起來的關係稱為原型鏈,這條鏈的末端一般總是預設的對象原型。
原型中讀的是從原型鏈上讀,寫是往自己裡面寫。
<script type="text/javascript"> function load() { function obj1() {//對象obj1 } function obj2() {//對象obj2 } obj2.prototype = new obj1(); //obj1賦值給obj2的原型 Object.prototype.foo = function () { alert("object"); //Object對象foo函數彈出object } testobj = new obj2(); //obj2賦值給測試對象testobj testobj.foo(); //執行測試對象的foo函數 obj1.prototype.foo = function () { alert("obj1"); //對obj1的原型函數foo重新賦值 } testobj.foo(); //在此執行測試對象的foo函數 } window.onload = load;</script>
運行結果:
結果分析:
我們先建立了對象obj1和obj2,把obj1的原型賦值給obj2,再Object的原型中添加函數foo顯示‘Object’,再把obj2賦值給測試對象testobj,執行testobj中的foo,我們發現實際執行的是Object中的foo,為什嗎?因為讀取的時候,一次從testobj---obj2---obj1---Object讀取,直到Object方能讀取到foo,所以說讀是從原型鏈從淺入深讀取。然後我們修改obj1的原型,使之也有foo函數,再次執行testobj的foo,我們發現實際執行的是obj1的foo,可見對obj1寫foo的時候是直接寫到自己的原型上的。
繼承是簡單的複製
<script type="text/javascript"> function load() { var father = new Object();//建立父物件 var son = new Object();//建立子物件 father.name = function () { alert('dad');//彈出dad } son.name = function () { alert('son');//彈出son } son.name = father.name; //把父物件的姓名賦值給子物件 father.name = function () { alert('new dad'); //覆寫父物件姓名為new dad } father.name(); //彈出父物件的姓名 son.name();//彈出子物件的姓名 } window.onload = load;//把load函數添加到頁面載入上 </script>
運行結果:
結果分析:
我們建立父物件father和子物件son,定義father的name為“dad”,son的name為“son”,再把father的name賦值給son,重新定義father的name為“new dad”。執行father的name,顯示為“new dad”,這個在我們意料之中;而執行son的name卻是“dad”而非“new dad”,可見繼承屬性,僅僅是複製父物件的屬性,而不是引用。
用了兩個簡單的執行個體說明了一下javascript中的原型和繼承,對於其更深層次的原型鏈和構造器,因為所學有限,等待以後的補充學習後繼續討論。