原型模式:將一個類的原型指向另個一類(實例化對象)的原型,實現對類的原型的共享。實現原理是基於JavaScript的原型鏈(prototype)
1.JavaScript中,所有函數(類)和部分原始數據類型(Number,String,Array,Function)具有prototype屬性。
2.在類的prototype屬性上設置的屬性,所有實例共享。
3.實例可修改prototype上的屬性。
如果修改的是值類型,只是當前實例發生更改。
如果修改的是引用類型,又分兩種情況:
①如果直接修改引用類型,則只影響當前實例的值。且修改后,由於引用地址的變化,之后所有對該實例上該屬性的更改都只作用於該實例。
②如果修改引用類型的屬性或項,則對父類發生更改,影響所有實例的值。
4.類可以直接設置靜態屬性,可直接通過 ”類名.屬性名 = 值 “設置和訪問,實例不可訪問。
1 var Person=(function(){ 2 var personCount=0; 3 function myPerson(name){ 4 this.name=name; 5 personCount++; 6 console.log('created new person,current person count:',personCount); 7 } 8 9 //靜態屬性,外部可通過Person.country直接訪問,實例不可訪問 10 myPerson.country='china'; 11 myPerson.prototype={ 12 //值類型,實例可修改,修改只影響當前實例 13 age:20, 14 //引用類型,實例可修改,修改里面的屬性會影響所有實例 15 address:{ 16 province:'四川', 17 city:'成都' 18 }, 19 sayHello:function(){ 20 console.log('hi,my name is ',this.name,',i am ',this.age); 21 }, 22 myAddress:function(){ 23 console.log(this.address.province,this.address.city); 24 } 25 }; 26 return myPerson; 27 }()); 28 29 console.log(Person.country); 30 31 var person1=new Person('zhangsan'); 32 person1.sayHello(); 33 var person2=new Person('lisi'); 34 person2.sayHello(); 35 var person3=new Person('wangww'); 36 person3.sayHello(); 37 38 //修改值類型原型屬性 39 person1.age=18; 40 console.log('修改person1.age后:'); 41 person1.sayHello(); 42 person2.sayHello(); 43 person3.sayHello(); 44 45 //1修改引用類型原型屬性的屬性 46 person1.myAddress(); 47 person2.myAddress(); 48 person3.myAddress(); 49 person1.address.city='德陽'; 50 console.log('修改person1.address.city后:'); 51 person1.myAddress(); 52 person2.myAddress(); 53 person3.myAddress(); 54 55 //2修改引用類型原型屬性 56 person1.address={ 57 province:'四川', 58 city:'巴中' 59 }; 60 console.log('修改person1.address后:'); 61 person1.myAddress(); 62 person2.myAddress(); 63 person3.myAddress(); 64 65 //3再次修改引用類型原型屬性的屬性 66 person1.address.city='綿陽'; 67 console.log('修改person1.address.city后:'); 68 person1.myAddress(); 69 person2.myAddress(); 70 person3.myAddress(); 71 72 //4再次修改引用類型原型屬性的屬性 73 person2.address.city='自貢'; 74 console.log('修改person2.address.city后:'); 75 person1.myAddress(); 76 person2.myAddress(); 77 person3.myAddress();
Console結果:
結果解析:
①第一次修改:修改person1.address.city=‘德陽’。此時,person1實例沒有address屬性,於是原型鏈向上查找,找到Person.prototype的address屬性,將Person.prototype.address值修改為‘德陽’。訪問三個實例的myAddress方法,由於三個實例均無address屬性,則都根據原型鏈查找到Person.prototype.address,結果為‘德陽’
②第二次修改:修改實例person1.address={province:'四川',city:'巴中'}。該操作將一個新的對象賦值給person1的address屬性,未對Person.prototype產生任何更改。訪問三個實例的myAddress方法,由於person1已有屬性address,則不再向上查找原型鏈,直接返回address的值。person2、person3均無address屬性,則都根據原型鏈查找到Person.prototype.address,結果為‘德陽’
③第三次修改:再次修改person1.address.city=‘綿陽’。此時person1已有屬性address,則不再向上查找原型鏈,直接修改person1的address屬性的city屬性,不對Person.prototype.address造成任何修改。訪問三個實例的myAddress方法,由於person1已有屬性address,則不再向上查找原型鏈,直接返回address修改后的值,返回‘綿陽’。person2、person3均無address屬性,則都根據原型鏈查找到Person.prototype.address,結果為‘德陽’
④第四次修改:修改實例person2.address.city='自貢'。此時,person2實例沒有address屬性,於是原型鏈向上查找,找到Person.prototype的address屬性,將Person.prototype.address值修改為‘自貢’。訪問三個實例的myAddress方法,由於person1已有屬性address,則不再向上查找原型鏈,直接返回address的值,返回‘綿陽’。person2、person3均無address屬性,則都根據原型鏈查找到Person.prototype.address,結果為‘自貢’