以下通過一段示例代碼,說明原型模型中的基本概念以及知識點。 部分摘自《JavaScript高級程式設計(第3版)》 ...
以下通過一段示例代碼,說明原型模型中的基本概念以及知識點。
<!DOCTYPE html> <html> <head> <title>原型模型</title> <script type="text/javascript"> function Person(){}; // Person.prototype.name="Lucy"; // Person.prototype.age=15; // Person.prototype.sayName=function(){ // alert(this.name); // }; //3.更簡單的原型語法 Person.prototype={ constructor:Person,//若constructor屬性值真的很重要,則需要手動設置回適當的值。 name:"Lucy", age:15, sayName:function(){ alert(this.name); } }; // var p1,p2; p1=new Person(); p2=new Person(); //hasOwnProperty()檢測一個屬性存在於實例中(true),還是存在於原型中(false) alert(p1.hasOwnProperty("name"));//false p1.name="Bob"; p1.job="student";//設置實例屬性 alert(p1.name);//"Bob",來自實例 alert(p1.hasOwnProperty("name"));//true alert(p1.sayName==p2.sayName);//true 檢查實例是否共用方法 alert(p1.job); alert(p1.hasOwnProperty("age"));//false alert(p1.hasOwnProperty("job"));//true // /*********************************** 2.原型與in操作符 *********************************************/ // /********單獨使用in操作符********/ // 通過對象能夠訪訪問到屬性時,返回true alert("job" in p1);//true alert("age" in p1);//true alert("name" in p1);//true alert("name" in p2);//true //該函數確定屬性是存在於原型對象中還是存在於實例對象中。 true:屬性為原型對象屬性;false:為實例對象屬性。 function hasPrototypeProperty(object,name){ return !object.hasOwnProperty(name)&&(name in object); } alert(hasPrototypeProperty(p1,"job")); alert(hasPrototypeProperty(p2,"name")); // /******************************/ // /********for-in ***********/ // 返回的是所有能夠通過對象訪問的、可枚舉的屬性,其中包括存在於原型中的屬性、也包括存在於實例中的屬性。 // Object.keys(object):接收一個對象作為參數,返回一個包含所有可枚舉屬性的字元串數組。 var keys=Object.keys(Person.prototype); alert(keys);//"name,age,sayName" var p1keys=Object.keys(p1); alert(p1keys);//"name,job" //順序即為for-in訪問時的順序 for(var prop in p1keys){ alert(p1keys[prop]); } //Object.getOwnPropertyNames(object) 獲取實例所有屬性,包括不可枚舉屬性 var p1allkeys=Object.getOwnPropertyNames(p1); alert(p1allkeys);//"name,job" var p1allkeys=Object.getOwnPropertyNames(Person.prototype); alert(p1allkeys);//constructor,name,age,job,sayName constructor屬性為不可枚舉 // /******************************/ // /*****************************************************************************************/ /************************************ 3.更簡單的原型語法 ****************************************/ //設置為簡單的原型語法後,Person.prototype設置為一個以對象字面量形式創建的新對象。最終結果相同,不過對象的constructor屬性不再指向Person。 //若constructor屬性值真的很重要,則需要手動設置回適當的值。 var friend=new Person(); alert(friend instanceof Object);//true alert(friend instanceof Person);//true alert(friend.constructor==Person);//false alert(friend.constructor==Object);//true var keys2=Object.keys(Person.prototype); alert(keys2);//constructor,name,age,job,sayName //簡單原型語法中手動設置constructor屬性之後,會導致它的[Enumerable]特性值為true,預設情況下原生的constructor值為false //重設構造函數,只適用於ECMAScript5相容瀏覽器 Object.defineProperty(Person.prototype,"constructor",{ enumerable:false, value:Person }); var keys3=Object.keys(Person.prototype); alert(keys3);//name,age,job,sayName // /**********************************************************************************************/ /************************************ 4.原型的動態性 ****************************************/ var per=new Person(); //可以隨時為原型添加屬性和方法,並且所有的修改能夠立即在所有對象實例中反映出來。 Person.prototype.sayHi=function(){ alert("Hi!"); } per.sayHi(); //若重構整個原型對象,就會在調用構造函數時為實例添加一個指向最初原型的[Prototype]指針,而把原型修改為另外一個對象就等於切斷了構造函數與最初原型之間的聯繫。 //實例中的指針僅指向原型,而不是構造函數。 function Student(){}; var st=new Student();//先創建實例對象 Student.prototype={//重構原型對象原型 constructor:Student, name:"Nike", age:20, speakEnglish:function(){ alert("Hello!"); } }; st.speakEnglish();//error 0: Object doesn't support property or method 'speakEnglish' // /**********************************************************************************************/ /************************************ 5.原型的問題 ****************************************/ //原型中所有屬性是被很多實例共用的,這種共用對於函數非常適合。對於包含基本值得屬性也沒有什麼,通過在實例上添加一個同名屬性就可以隱藏原型中對應的屬性。 //然而,對於包含引用類型的值來說,就會存在問題。如下例所示。 function Singer(){}; Singer.prototype={ constructor:Singer, name:"Nike", age:30, albums:["Suger","Live"]//"Suger","Live"是所有實例對象的共用albums集合 }; var s1=new Singer(); var s2=new Singer(); s1.albums.push("Flowers");//“Flowers”是s1的唱片集 alert(s1.albums);//"Suger","Live","Flowers" alert(s2.albums);//"Suger","Live","Flowers",而"Flowers"不是s2的唱片 alert(s1.albums===s2.albums);//指向同一個albums /**********************************************************************************************/ </script> </head> <body> </body> </html>
部分摘自《JavaScript高級程式設計(第3版)》