检测原型对象是否被篡改需多角度交叉验证:比对原型链快照、校验内置方法原生性、检查构造器与原型双向一致性、验证冻结状态及属性完整性。

检测原型对象是否被篡改,核心是确认它是否还保持原始结构和行为——不是抓“谁改的”,而是判断“现在对不对”。JavaScript 没有变更监听机制,但可通过多角度交叉验证快速识别异常。
比对初始化时的原型链快照
在脚本最早期(如页面加载完成前、第三方库注入前)记录关键原型链路径,后续比对即可发现替换:
- 用 Object.getPrototypeOf() 逐层获取,例如:
Object.getPrototypeOf(Array.prototype)应始终是Object.prototype,再往上应为null - 将路径转为数组再序列化,如
JSON.stringify([Array.prototype, Object.prototype, null]),存为只读基准值 - 运行中重新采集并严格比对字符串或哈希值;不一致即说明某层被显式赋值覆盖(如
Array.prototype = {})
校验内置方法是否仍为原生实现
篡改常表现为重写原型方法或删除关键属性,可从行为和特征两方面检查:
- 确认方法存在且为函数:
typeof Array.prototype.push === 'function' - 检查是否保留原生标识:
Array.prototype.push.toString().includes('[native code]')(注意:部分环境会屏蔽该字符串,需配合其他手段) - 重点验证 Object.prototype.hasOwnProperty 是否可用、未被重写——它是几乎所有属性检测的基础,一旦失效,整个对象系统可能已失稳
验证构造器与原型双向一致性
正常情况下,对象与其构造器的原型关系必须对称。破坏这一关系是篡改的典型痕迹:
- 对任意实例
obj,执行obj.constructor && Object.getPrototypeOf(obj) === obj.constructor.prototype,返回false即异常 - 特别检查全局构造器:
Array.prototype === Array.prototype必须为真;若Array.prototype被替换成新对象,但Array.constructor.prototype未同步更新,就会断裂 - 避免依赖
__proto__,它非标准且可被修改;始终优先使用 Object.getPrototypeOf()
检查冻结/密封状态与意外属性
原生原型在合规环境中应处于受保护状态,异常开放往往意味着已被干预:
- 执行
Object.isFrozen(Object.prototype),现代浏览器和严格模式下应返回true;若为false,说明它曾被解冻并可能被修改 - 枚举
Object.getOwnPropertyNames(Object.prototype),对比预期列表(如['hasOwnProperty', 'toString', 'valueOf', ...']),出现额外属性(如'hackFlag')即高危信号 - 注意:添加不可枚举属性不会影响
for...in,但可用 Object.getOwnPropertyNames() 或 Object.getOwnPropertyDescriptors() 捕获


















