JavaScript原型安全需三重防护:先用Object.freeze()冻结原型对象,使属性不可写、不可配置;再锁定构造函数的prototype属性为不可配置;最后对敏感方法用Object.defineProperty精确设为不可写、不可配置、不可枚举。

JavaScript 原型对象本身无法完全“禁止访问”,但可以通过组合手段让核心方法**不可被覆盖、不可被删除、不可被枚举、甚至无法被意外调用**——关键不是藏起来,而是锁住行为边界。
冻结原型对象本身
这是最基础也最有效的防线。对原型调用 Object.freeze() 后,所有已有属性自动变为 writable: false 和 configurable: false,意味着:
- 不能修改方法体(
MyClass.prototype.method = newFn失效) - 不能删除该方法(
delete MyClass.prototype.method静默失败) - 不能重新定义其描述符(
Object.defineProperty报错)
务必在类定义完成、任何实例创建前执行:
```jsclass MyClass { /* ... */ }
Object.freeze(MyClass.prototype);
```
锁定构造函数的 prototype 属性
仅冻结原型对象还不够——攻击者仍可能直接替换整个原型:MyClass.prototype = {}。需进一步锁死构造函数的 prototype 属性:
立即学习“Java免费学习笔记(深入)”;
Object.defineProperty(MyClass, 'prototype', {
configurable: false
});
```
这样连原型引用本身都不可变更,从根源上杜绝“换皮”式篡改。
用 defineProperty 精确控制关键方法
对特别敏感的方法(如 save、validate),不依赖默认赋值,而用 Object.defineProperty 显式声明:
-
writable: false→ 阻止方法被重赋值 -
configurable: false→ 阻止被删除或重定义 -
enumerable: false→ 不出现在for...in或Object.keys()中,降低暴露面
Object.defineProperty(MyClass.prototype, 'save', {
value: function() { /* 核心逻辑 */ },
writable: false,
configurable: false,
enumerable: false
});
```
避免原型污染入口:不裸露可重写钩子
如果设计了供子类扩展的钩子方法(如 beforeSave),不要把它放在原型上任由覆盖。更安全的做法是:
- 将其设为私有实例方法(
this.#beforeSave = () => {}),利用 # 私有字段天然隔离 - 或要求子类必须显式调用
super.beforeSave(),并在父类中加入运行时校验:if (!this.#validated) throw new Error('must call super.beforeSave');
本质是减少“可被外部触达并修改”的表面,而不是在表面加锁。


















