可以通過prototype來為已經定義好的的"類"添加屬性和方法。這里來了解一下prototype的基礎知識。prototype是"構造函數"的屬性,不是實例的屬性.
示例:
function HiClass() { this.sayHi = function(){ alert("hi"); } } var obj = new HiClass(); alert(HiClass.prototype);//outputs [object, object] alert(obj.prototype);//outputs undefined
在用prototype的方式實現繼承一個類的時候,要注意其可能覆蓋別的prototype方式添加的屬性和方法。如果HiClass.prototype.prop = 'value'是在HiClass.prototype = new HelloClass()之前則不會有prop屬性,如果在執行HiClass.prototype = new HelloClass()之后,HiClass的實例中會有prop屬性,這個應該很好理解。但是要注意代碼中不要不小心存在這樣的bug。
示例:
function HiClass() { this.sayHi = function(){ alert("hi"); } } function HelloClass() { this.sayHello = function(){ alert("hello"); } } //HiClass.prototype.prop = 'value'; //this.prop = function(){}寫法是可以繼承的,兩種寫法有區別滴 HiClass.prototype = new HelloClass(); HiClass.prototype.prop = 'value'; var obj = new HiClass(); obj.sayHello(); alert(obj.prop);
在JavaScript中有一個prototype鏈,在對一個對象實例上調用方法或者獲取屬性的時候,先看實例對應的類有沒有對應的定義,沒有的話會沿着prototype鏈一直找,找不到則為undefined。如果某類都有
定義,則調用本身的定義。Object.prototype.foo = function(){}會對所有以定義的方法起作用,javascript中Object對象是所有對象的基類
示例:
function Object2() { this.sayHi = function(){ alert("hi Object2"); } } function Object3() { this.sayHi = function(){ alert("hi Object3"); } this.sayHello = function(){ alert("hello Object3"); } }
Object2.prototype = new Object3(); var obj = new Object2(); obj.sayHi(); //hi Object2 調用obj.sayHi();的時候,sayHi在Object2里已經定義,則調用本身的定義。 obj.sayHello(); //hi Object3 Object.prototype.foo = function(){ //會對所有以定義的方法起作用,javascript中Object對象是所有對象的基類 alert("f00 Object"); }; obj.foo(); //f00 Object Object2.foo(); //f00 Object Object3.foo(); //f00 Object a.foo(); //報錯
如果在實例里添加的屬性和方法與prototype里的屬性和方法重名,相對於實例和prototype都有這個屬性和方法,只是由於prototype鏈的訪問順序,先訪問到實例中的屬性和方法。如下面的例子說明了這一點
function Test(){}; Test.prototype.prop1 = 'prop value'; var obj = new Test(); //obj如果是一個方法又不一樣嘍;obj.prototype = new Test();不會繼承滴 obj.prop1 = 'instance value'; alert(obj.prop1 );//outputs instance value alert(obj.hasOwnProperty("prop1"));//outputs true delete obj.prop1;alert(obj.prop1 ); //outputs prop value 由於prototype鏈的訪問順序,先訪問到實例中的屬性和方法,刪除的是第一個屬性 alert(obj.hasOwnProperty("prop1"));//outputs false alert("prop1" in obj);//outputs true delete Test.prototype.prop1;alert(obj.prop1 );//outputs undefined
再來看看一些構造函數和prototype的使用:
var myObj = { prop1:'value1', prop2:'value2' } Object.prototype.foo = function(){ alert("f00 Object"); }; //等價於 //var myObj = new Object(); //myObj.prop1 = 'value1'; //myObj.prop2 = 'value2'; alert(myObj.prop2); //value2 myObj.foo(); // f00 Object
同時也可以如下的方式對prototype賦值,可以一次添加多個屬性和方法
function TestCls(){ } TestCls.prototype = { //可以一次添加多個屬性和方法 prop1:'value1', prop2:'value2' }; myObj = new TestCls(); alert(myObj.prop2); //value2
上面的做法中有一個問題是改變prototype后,constructor也改變了。
所以要將prototype.constructor之前的值,比如第一個例子中要加上 HiClass.prototype.constructor=HiClass;constructor 屬性返回對創建此對象的數組函數的引用
//上面的做法中有一個問題是改變prototype后,constructor也改變了。 //所以要將prototype.constructor之前的值,比如第一個例子中要加上 HiClass.prototype.constructor=HiClass function HiClass() { this.sayHi = function(){ alert("hi"); } } function HelloClass() { this.sayHello = function(){ alert("hello"); } } HiClass.prototype = new HelloClass(); HiClass.prototype.constructor=HiClass //constructor 屬性返回對創建此對象的數組函數的引用。
