数组去重本身不引发原型链污染,但用普通对象做哈希表或for...in遍历时会意外访问object.prototype上的污染属性;应改用hasownproperty、map或set,优先使用set;处理对象数组时避免依赖json.stringify,推荐用map或字段拼接键;开发中应冻结原型、用object.create(null)并启用严格模式。

数组去重本身不会直接引发原型链污染,但问题常出在**去重过程中遍历或构造对象的方式不当**——尤其是用普通对象({})做哈希表、或用 for...in 遍历对象键名时,意外访问到被污染的 Object.prototype 上的属性,导致逻辑错乱甚至安全风险。
别用 for...in 遍历对象做去重映射
很多老式去重写法依赖 for...in 遍历对象属性来判断是否已存在:
- ❌ 错误示例:
const seen = {};<br>arr.forEach(item => { if (!seen[item]) seen[item] = true; });
一旦攻击者执行Object.prototype.admin = true,所有字符串类型的item(如"admin")都会命中这个污染属性,误判为“已存在” - ✅ 正确做法:改用
Object.hasOwnProperty显式检查自有属性if (!seen.hasOwnProperty(item)) seen[item] = true; - 更优方案:直接用
Map或Set,它们不继承自Object.prototype,天然免疫污染
优先使用 Set,避开对象哈希陷阱
Set 是最安全、最简洁的去重方式,它内部不依赖原型链查找,也不暴露 __proto__ 等敏感接口:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ✅ 推荐写法:
const unique = [...new Set(arr)]; - 对原始类型(数字、字符串、布尔值)完全可靠,且保持原顺序
- 若需兼容旧环境,可用
Array.from(new Set(arr))替代扩展运算符
处理对象数组时,避免 JSON.stringify 依赖原型方法
有些方案用 JSON.stringify(item) 生成唯一键存入对象哈希表,但若 item 自身或其原型上重写了 toJSON 或 toString,可能引入不可控行为:
- ⚠️ 风险点:如果
Object.prototype.toString被污染(例如返回固定字符串),所有对象的JSON.stringify结果可能异常趋同,导致去重失效 - ✅ 更可控做法:
用Map存储对象引用(适合浅层去重)
或手动提取确定字段组合成键,例如:`${item.id}-${item.name}` - 如必须序列化,先冻结关键原型:
Object.freeze(Object.prototype),再执行解析逻辑
开发习惯上主动隔离污染影响
即使去重逻辑本身安全,整个运行环境仍可能被污染。建议在应用启动初期就加固:
- 在首个
<script></script>标签顶部立即执行:Object.freeze(Object.prototype); Object.freeze(Array.prototype); - 配置类、映射表等场景,统一用
Object.create(null)创建空原型对象,彻底断开继承链 - 测试时启用严格模式(
"use strict"),让原型篡改操作直接报错,便于早期发现
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










