在上篇文章中,咱們說過,原型對象也有缺點:javascript
function Person(){} Person.prototype={ name:"nUll", friends:["gay1","gay2"], sayName:function(){ alert(this.name); } }; var person1=new Person(); var person2=new Person(); person1.friends.push("gay3"); alert(person2.friends); //gay1,gay2,gay3 //WTF? person2 的friends 怎麼會有gay3? 好吧,若是這就是你想要的結果,就當書上什麼也沒說-_-
直接點的處理方式是組合使用構造函數模式和原型模式:html
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.friends=["gay1","gay2"]; } Person.prototype={ constructor:Person, sayName:function(){ alert(this.name); } } var person1=new Person("nUll",25,"software"); var person2=new Person("mywei",25,"software"); person1.friends.push("gay3"); alert(person1.friends); // gay1,gay2,gay3 alert(person2.friends); //gay1,gay2 alert(person1.friends===person2.friends); //false alert(person1.sayName===person2.sayName); //true
這與開頭的例子的區別在於,屬性在構造函數中定義,而方法在原型中定義,於是每一個實例有獨立的friends屬性.這種方式建立實例對象能夠說是最普遍,認同度最高的一種建立自定義類型的方法.java
在初步瞭解原型方法後,就應該能理解下面代碼的思想,不過要注意,下面不能使用"字面量"的方式重寫原型,由於那樣會切斷現有實例與新原型之間的聯繫:app
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; if(typeof this.sayName!="function"){ Person.prototype.sayName=function(){ alert(this.name); }; } } var person1=new Person("nUll",25,"software"); person1.sayName();
寄生構造函數模式,不知道大家是否還記得上篇文章中的這段代碼:函數
String.prototype.startsWith=function(text){ return this.indexOf(text)==0; } var msg="Hello world"; alert(msg.startsWith("Hello")); //true 說的好!但這毫無心義(這裏僅是提供擴展的示例,並非說擴展的startsWith方法多麼的精闢!)
若是咱們不想擴充原生對象例如Array,則能夠使用寄生構造函數模式:this
function SpeciaArray(){ var values=new Array(); values.push.apply(values,arguments); values.toPipedString=function(){ return this.join("|"); }; return values; } var friends=new SpeciaArray("gay1","gay2","gay3"); alert(friends.toPipedString()); //gay1|gay2|gay3 alert(friends instanceof Object); //true alert(friends instanceof SpeciaArray); //false alert(friends instanceof Array); //true
下篇將討論javascript中的繼承.歡迎拍磚.spa