object.create(null) 创建的对象无原型链,彻底避免属性名冲突和原型污染,适合作为安全的键值对存储;普通对象因继承 object.prototype 而存在 tostring 等方法名冲突及 for...in 遍历风险。

用 Object.create(null) 创建对象,能彻底切断与 Object.prototype 的连接,得到一个没有 toString、hasOwnProperty、constructor 等任何默认方法的“空”对象,特别适合做键值对存储,避免属性名冲突和原型污染。
为什么普通对象不适合作为散列字典
普通对象(如 {} 或 new Object())默认继承自 Object.prototype,这意味着所有键名都可能与原型上的方法名冲突。例如,当你要存一个键名为 "toString" 的数据时:
const obj = {};
obj.toString = "custom value";
console.log(obj.toString()); // ❌ 调用的是原型方法,不是你设的字符串
更严重的是,for...in 会遍历原型链上的可枚举属性,Object.keys() 虽然只返回自身属性,但若原型被篡改(比如恶意注入 Object.prototype.pollute = 1),仍可能引发意外行为。
Object.create(null) 的核心优势
它创建的对象没有 __proto__,也没有隐式原型链,因此:
- 所有属性都是“自有属性”,不存在继承来的键
- 不会受
Object.prototype上新增属性的影响(防原型污染) - 作为 Map 的轻量替代,在只做字符串键映射时性能更高、内存更省
- 配合
in、hasOwnProperty(需手动绑定)或Object.prototype.hasOwnProperty.call安全判断存在性
实用写法与注意事项
直接使用没问题,但要注意缺失常用方法带来的操作差异:
- 不能直接调用
obj.toString()—— 会报TypeError;需要转成普通对象再处理,或用JSON.stringify(obj) - 判断属性是否存在推荐:
Object.prototype.hasOwnProperty.call(obj, key),而不是obj.hasOwnProperty(key)(因为后者不存在) - 遍历时用
Object.keys(obj)、Object.entries(obj)安全可用(它们只查自身属性) - 若需扩展能力,可手动挂载方法,例如:
obj.keys = () => Object.keys(obj);
典型应用场景
适合对健壮性和确定性要求高的场景:
- HTTP 请求头对象(键名完全由用户/服务端控制,如
"Content-Type"、"set-cookie") - 编译器/解析器中的符号表(变量名、标签名等标识符映射)
- 路由匹配缓存、事件监听器注册表(避免
"on"、"off"等键与原型方法同名导致覆盖) - 配置合并工具中临时收集键值,防止
"constructor"这类特殊键触发意外逻辑











