JavaScript设计模式-原型模式
原型模式:将一个类的原型指向另个一类(实例化对象)的原型,实现对类的原型的共享。实现原理是基于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,结果为‘自贡’