直接冻结原型对象有效,但仅限自身属性,不递归冻结原型链或阻止prototype重赋值;须在定义完方法且创建实例前冻结,并配合defineProperty锁定prototype属性。

直接对原型对象调用 Object.freeze() 是有效的,但需注意:冻结只作用于**当前对象自身属性的可配置性、可写性和可枚举性**,不会递归冻结其原型链上的对象,也不能阻止原型链被重新赋值(如重写 constructor.prototype)。关键在于「冻结时机」和「冻结范围」。
必须在原型对象被广泛使用前冻结
一旦构造函数的原型已被实例引用或被其他代码扩展(比如添加了方法),再冻结就无法撤销已有修改,也无法阻止已存在的引用绕过冻结做间接操作。
- 推荐在定义完所有原型方法后、创建任何实例前立即冻结
- 避免在模块外部暴露未冻结的原型引用
- 示例:
function Person(name) { this.name = name; }
Person.prototype.sayHello = function() { return `Hi, I'm ${this.name}`; };
// ✅ 正确:定义完毕立刻冻结
Object.freeze(Person.prototype);
// ❌ 错误:冻结太晚,可能已有实例或第三方扩展
const p = new Person('Alice');
Object.freeze(Person.prototype); // 已无法保护 p 的内部行为一致性
冻结不能阻止 __proto__ 或 prototype 被重新赋值
Object.freeze() 不影响对象的 __proto__ 访问器,也不锁定构造函数的 prototype 属性本身——后者仍是可写的。恶意代码仍可执行:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Person.prototype = { ... };(覆盖整个原型) -
obj.__proto__ = {};(修改单个实例原型链) - 因此,仅靠
freeze不足以实现强防护,需配合其他机制
增强防护:组合使用 Object.freeze + 防篡改模式
若需更高安全性,可结合以下实践:
立即学习“Java免费学习笔记(深入)”;
- 用
Object.defineProperty将构造函数的prototype设为不可写、不可配置 - 对原型对象本身调用
Object.freeze,封印自有属性 - 必要时用
Object.seal或Object.preventExtensions限制新增属性 - 示例:
function User(id) { this.id = id; }
User.prototype.getId = function() { return this.id; };
// 冻结原型对象
Object.freeze(User.prototype);
// 锁定构造函数的 prototype 属性(防止被覆盖)
Object.defineProperty(User, 'prototype', {
writable: false,
configurable: false
});
冻结后的行为表现
冻结原型后,尝试以下操作将静默失败(非严格模式)或抛出 TypeError(严格模式):
-
User.prototype.newMethod = function() {};(新增属性) -
User.prototype.getId = null;(修改现有属性值) -
delete User.prototype.getId;(删除属性) - 但
new User(123)仍能正常继承并调用getId

















