object.preventextensions仅阻止对象自身新增属性,不限制原型链修改;已有属性仍可读写、删除或重定义,但无法添加新属性,且不影响__proto__或prototype的变更。

Object.preventExtensions 并不“冻结原型扩展”,它防止的是**对象自身属性的新增**,对原型链上的属性或方法没有任何影响。也就是说,它只作用于目标对象本身,不会阻止你通过修改其 __proto__ 或 prototype(如果是函数)来改变原型,也不会阻止原型上的属性被添加或修改。
它真正的作用:禁止新增自身属性
调用 Object.preventExtensions(obj) 后,该对象不能再添加新属性(包括使用点号、方括号或 Object.defineProperty),但已有属性仍可读写、可配置、可枚举(除非另有设置)。
- ✅ 允许:修改已有属性值、删除已有属性、重定义已有属性描述符(只要 configurable 为 true)
- ❌ 禁止:添加新属性(
obj.newProp = 1、obj["x"] = 2、Object.defineProperty(obj, "y", {...})) - ⚠️ 注意:不影响原型——如果
obj.__proto__.sharedMethod = function(){},依然可以成功,且obj.sharedMethod会立即可用
为什么它不控制原型?
JavaScript 的原型机制是独立于单个对象的。一个对象的 [[Prototype]] 是一个引用,preventExtensions 不会锁定这个引用关系,也不会冻结它所指向的对象。例如:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const proto = {};
const obj = Object.create(proto);
Object.preventExtensions(obj);
obj.existing = "ok"; // ✅ 允许(已有属性可赋值)
obj.newProp = "fail"; // ❌ 静默失败(非严格模式)或报错(严格模式)
// 但原型仍可修改:
proto.fromProto = "yes"; // ✅ 成功
console.log(obj.fromProto); // → "yes"
想真正限制原型相关行为?用更严格的 API
若目标是让对象“彻底封闭”,需组合使用:
-
Object.preventExtensions(obj):停掉新属性 -
Object.seal(obj):在 preventExtensions 基础上,把所有现有属性设为configurable: false(不能删、不能改描述符) -
Object.freeze(obj):在 seal 基础上,把所有现有数据属性设为writable: false(值不可改) - ⚠️ 以上三者都**不递归冻结原型**。如需冻结原型链,必须显式对原型对象也调用相应方法(例如
Object.freeze(Object.getPrototypeOf(obj)))
检查对象是否已禁止扩展
用 Object.isExtensible(obj) 判断:
const obj = {};
console.log(Object.isExtensible(obj)); // → true
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // → false
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










