JS原型属性疑问:修改p1.y后为何p2.y仍为200而非201?
为什么修改p1.y后p2.y没变化?
嘿,这个问题戳中了JavaScript原型链里一个很容易踩坑的点——属性遮蔽(Shadowing),我给你一步步拆解清楚:
首先先把你的代码贴出来方便对照:
function person(){ this.x = 100; } person.prototype.y = 200; var p1 = new person(); var p2 = new person(); ++p1.y; console.log(p1.y); // 输出201 console.log(p2.y); // 输出200
核心逻辑拆解
初始状态:你把
y=200挂在了person的原型对象上,这时候p1和p2这两个实例本身并没有自己的y属性——它们访问y的时候,是顺着原型链“往上找”,找到原型上的那个公共的y。执行
++p1.y的本质:这个操作是「读→改→存」的三步组合:- 第一步:读取
p1.y,此时因为p1自己没有y,所以找到原型上的200; - 第二步:把200加1变成201;
- 第三步:重点来了!JavaScript不会直接去修改原型上的那个公共
y,而是会在p1这个实例对象上新建一个属于它自己的y属性,把201存进去。这就叫“属性遮蔽”——实例自己的属性会遮蔽原型上的同名属性。
- 第一步:读取
后续访问差异:
- 再访问
p1.y时,JS会优先取实例自己的y(也就是201),不会再去原型找了; - 而
p2从来没被修改过y,它自己还是没有y属性,所以依然去原型上取那个没被改动过的200。
- 再访问
验证这个逻辑
你可以加几行代码验证我说的:
console.log(p1.hasOwnProperty('y')); // 输出true,说明p1现在有自己的y属性 console.log(p2.hasOwnProperty('y')); // 输出false,p2还是没有自己的y console.log(person.prototype.y); // 输出200!原型上的y根本没被碰过
如果真的想修改原型上的y,让所有实例都看到变化,你得直接操作原型:
person.prototype.y++; // 直接改原型的y console.log(p1.y); // 201 console.log(p2.y); // 201
内容的提问来源于stack exchange,提问作者Jagan
相关产品推荐
相关产品推荐

