function Mother () {
}
Mother.prototype = { // Mother的原型,可以认为是“Grandmother”
age: 18,home: ['Beijing','Shanghai']
};
Person.prototype = new Mother(); // Person的原型为Mother,所有Person实例的原型都是同一个Mother实例
// p1与p2有两层proto,第一层是Mother,没有实例属性,第二层是Grandmother
var p1 = new Person('Jack'); //p1:'Jack'; proto:{proto:18,['Beijing','Shanghai']}
var p2 = new Person('Mark'); //p2:'Mark'; proto:{proto:18,'Shanghai']}
p1.age = 20;
/* 实例不能改变原型的基本值属性
- 在p1实例下增加一个age属性的普通操作,与原型无关。跟var o={}; o.age=20一样。
- p1:下面多了个属性age,而proto跟 Mother.prototype一样,age=18。
- p2:只有属性name,proto跟 Mother.prototype一样
*/
p1.home[0] = 'Shenzhen';
/* 原型中引用类型属性的共享
- 此时p1没有home实例属性,从原型属性里找到了home,则改变了Person的原型
- p1:'Jack',20; proto:{proto:18,['Shenzhen','Shanghai']}
- p2:'Mark'; proto:{proto:18,'Shanghai']}
*/
p1.home = ['Hangzhou','Guangzhou'];
/* 其实跟p1.age=20一样的操作,为p1添加实例属性。
- p1:'Jack',20,['Hangzhou','Guangzhou']; proto:{proto:18,'Shanghai']}
- p2:'Mark'; proto:{proto:18,'Shanghai']}
*/
delete p1.age;
/* 删除实例的属性之后,原本被覆盖的原型值就重见天日了
Person.prototype.lastName = 'Jin';
/* 改写原型,动态反应到实例中
- 注意,这里我们改写的是Person的原型(即Mother实例),为其添加一个lastName实例属性,等同于Mother.lastName='Jin'
- 这里并不是改Mother.prototype(Grandmother)
- p1:'Jack','Guangzhou']; proto:{'jin',proto:18,'Shanghai']}
- p2:'Mark'; proto:{'jin','Shanghai']}
*/
// 重点!!!
Person.prototype = {
age: 28,address: { country: 'USA',city: 'Washington' }
};
var p3 = new Person('Obama');
/* 重写原型!而不是在原型中增减属性。这个时候Person的原型已经完全变成一个新的对象了
- 换成这样理解:var a=10; b=a; a=20; c=a。所以b不变,变得是c,p3与Mother实例无关
- p1:'Jack','Shanghai']}
- p3:'Obama';proto: 28 {country: 'USA',city: 'Washington'}
*/
Mother.prototype.no = 9527;
/* 改写原型的原型,动态反应到实例中,相当于修改了Grandmother的实例属性
- 注意,这里我们改写的是Mother.prototype,p1和p2会变,p3不变
- p1:'Jack','Shanghai'],9527}
- p2:'Mark'; proto:{'jin',9527}
- p3:'Obama';proto: 28 {country: 'USA',city: 'Washington'}
*/
Mother.prototype = {
car: 2,hobby: ['run','walk']
};
var p4 = new Person('Tony');
/* 重写原型的原型!这个时候Mother的原型已经完全变成一个新的对象了!
- 由于上面Person与Mother已经断开联系了,这时候Mother怎么变已经不影响Person了,p1与p2无影响
- p4:'Tony';proto: 28 {country: 'USA',city: 'Washington'}
*/
Person.prototype = new Mother(); //再次绑定
var p5 = new Person('Luffy');
// 这个时候如果需要应用这些改动的话,那就要重新将Person的原型绑到Mother上了
// 此时p1与p2无变化
// p5:'Luffy';proto:{proto: 2,['run','walk']}
在原型中增减属性,实例会随之变化,但如果重写原型,实例的原型属性不变。
同理,若在原型的原型中增减属性,实例会随之变化,但如果重要原型的原型,原型不会变化,则实例也不会变化。