object.preventextensions仅冻结目标对象自身,不阻止原型链扩展;可修改已有属性值,但不能添加新属性;需手动遍历原型链调用才能限制整个继承链。

Object.preventExtensions 只作用于目标对象本身,**不会影响原型链上的属性添加行为**,也无法阻止对原型链上已有属性的读写或修改。它仅禁止在该对象上定义新属性(包括自有属性和可枚举/不可枚举属性),但不冻结已有属性,也不限制原型链访问。
只冻结自身,不冻结原型
调用 Object.preventExtensions(obj) 后,你不能再给 obj 添加新属性,但它的原型对象(如 obj.__proto__ 或 Object.getPrototypeOf(obj))仍可自由扩展。子对象或继承链不受约束。
- ✅
obj.newProp = 1→ 报错(严格模式)或静默失败(非严格模式) - ✅
Object.defineProperty(obj, 'x', {...})→ 失败(无法定义新属性) - ✅
obj.__proto__.newOnProto = 2→ 允许(原型对象未被锁定) - ✅
Object.getPrototypeOf(obj).another = 3→ 允许
如何检查对象是否被禁止扩展
使用 Object.isExtensible(obj) 判断。返回 false 表示已调用 preventExtensions(或更严格的 seal/freeze)。
-
Object.isExtensible({})→true -
const o = {}; Object.preventExtensions(o); Object.isExtensible(o)→false -
Object.isExtensible(Object.getPrototypeOf(o))→ 仍为true(除非显式对其调用)
想真正“隔离”原型链?需手动处理
JavaScript 没有内置机制让 preventExtensions 递归作用于原型链。若需彻底防止通过原型添加属性,必须逐层调用:
- 先获取完整原型链:
let p = obj; while (p) { /* 处理 p */; p = Object.getPrototypeOf(p); } - 对每个非
null原型对象调用Object.preventExtensions(p) - 注意:
Object.prototype是所有对象的终点,禁止扩展它会影响全局(不推荐)
与 seal / freeze 的区别
三者层级递进,但都只作用于目标对象:
-
preventExtensions:仅禁新增属性,允许改值、删属性、改描述符 -
Object.seal:在 preventExtensions 基础上,还禁止删除属性、修改属性描述符(但值仍可改) -
Object.freeze:最严格,还禁止修改所有属性值(数据属性变只读,访问器属性仍可触发 set/get)
它们都不自动作用于原型链 —— 这是设计使然,不是 bug。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











