object.create(null)创建的对象无原型链,免疫原型污染;其__proto__为undefined,不继承任何方法,适用于配置缓存、路由映射等场景,但需注意属性检查、遍历及方法调用方式。

用 Object.create(null) 创建的对象本身就没有原型链,自然不会被原型链污染——这是最直接、最底层的防御方式。
为什么无原型对象能免疫污染
普通对象(如 {})的 __proto__ 指向 Object.prototype,一旦该原型被恶意注入属性(如 __proto__.admin = true),所有普通对象都会继承这个属性。而 Object.create(null) 创建的对象:
-
Object.getPrototypeOf(obj) === null,原型链在起点就终止 -
obj.__proto__是undefined,不指向任何可写原型 - 没有
toString、hasOwnProperty等继承方法,也就没有可被覆盖或触发的“入口”
典型安全使用场景
不是所有地方都适合用无原型对象,但以下几类数据结构强烈推荐:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
配置缓存表:如
const configMap = Object.create(null); configMap['env'] = 'prod'; -
路由映射表:如
const routes = Object.create(null); routes['/api/user'] = handler; -
用户输入键名的字典:比如统计日志字段、解析 query string,避免
input.toString被当作键名误用
操作时需注意的关键细节
它“空”得彻底,所以不能像普通对象那样随意调用方法:
- 判断属性存在请用
Object.prototype.hasOwnProperty.call(obj, key),而非obj.hasOwnProperty(key) - 遍历键名用
Object.keys(obj)或for (let k in obj)(因无原型,in只查自身) - 需要
toString功能?手动定义:obj.toString = () => `[object MapLike]`,或统一用JSON.stringify(obj) - 不要对它调用
obj instanceof Object——结果恒为false,这不是 bug,是设计如此
配合其他措施才真正可靠
单靠 Object.create(null) 能解决“存储层”的污染风险,但业务逻辑仍需整体设防:
- 外部数据合并前过滤危险键:
__proto__、constructor、prototype及其大小写变体 - 关键原型尽早冻结:
Object.freeze(Object.prototype),放在所有第三方脚本之前执行 - 避免深拷贝时递归污染:用白名单字段校验代替无条件
Object.assign或lodash.merge
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










