object.setprototypeof只改变对象的[[prototype]]内部槽,不修改自有属性的描述符;自有属性的writable、enumerable、configurable等保持原样,仅影响属性查找路径和继承行为。

Object.setPrototypeOf 不会修改对象自身的属性描述符(如 writable、enumerable、configurable),它只改变对象的 [[Prototype]] 内部槽,也就是属性查找的起点。自有属性的描述符保持完全不变——无论是定义时设置的,还是后续用 Object.defineProperty 修改过的。
自有属性描述符不受影响
- 原来
obj.x是writable: false,设新原型后,Object.getOwnPropertyDescriptor(obj, 'x')返回的仍是原描述符; -
delete obj.x是否成功,取决于该属性本身的configurable值,与原型无关; -
for...in遍历结果变化,不是因为描述符变了,而是因为可枚举继承属性来源切换了——新原型上新增的可枚举属性会进入遍历,旧原型上的则消失。
原型上属性的描述符才起作用
当访问一个自有属性不存在的键(如 obj.y),查找落到原型上时,最终行为由原型对象中该属性的描述符决定:
- 若
proto.y是writable: false,且obj.y未定义,则obj.y = 100不会修改原型上的值,而是在obj上新建一个自有属性(前提是obj可扩展); - 若
proto.y是writable: true,但obj已有同名自有属性,那赋值仍操作自有属性,原型描述符不参与; - 若
proto.y是configurable: false,你无法通过delete obj.y删除它(除非obj.y本身是自有且configurable: true)。
冻结或密封对象会阻止 setPrototypeOf 执行,但不改变已有描述符
-
Object.freeze(obj)后调用Object.setPrototypeOf(obj, newProto)会抛出TypeError,这是对操作本身的限制,不是对描述符的干预; -
Object.seal(obj)同样禁止修改原型,但自有属性描述符照常存在、照常生效; - 描述符本身是否被“保护”,只取决于定义时或
defineProperty设置的值,setPrototypeOf完全不触碰它们。
真正受影响的是“访问行为”,不是“定义状态”
-
Object.getOwnPropertyDescriptors(obj)返回的永远只是obj自身属性的描述符,不会包含原型链上的; -
Object.getOwnPropertyDescriptor(obj, key)只查自有属性,查不到原型上的,所以返回undefined并不表示描述符被改了,只是没定义在obj上; -
key in obj的结果变化,是因为in操作符检查整个原型链上的可枚举属性,而链变了——但每个链上属性的描述符本身没动。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











