Object.create(null)的核心价值是切断与Object.prototype的一切联系,创建无原型、无内置方法、无隐式行为的纯净对象,适用于哈希表、配置缓存等需绝对干净结构的场景。

Object.create(null) 的核心价值,是切断对象与 Object.prototype 的一切联系,造出一个真正“白纸一张”的容器。它不为继承设计,只为纯粹的数据承载而存在。
为什么普通空对象不够“干净”?
{} 或 new Object() 看似空,实则暗藏原型链:它们的 __proto__ 指向 Object.prototype,因此自带 toString、hasOwnProperty、valueOf、constructor 等方法。这些方法既是便利,也是隐患:
- 键名一旦撞上 toString、hasOwnProperty 等,就会覆盖原型方法,导致后续调用失效或行为异常
- for...in 遍历时,若 Object.prototype 被意外扩展(如某些老库或恶意代码),会把新增属性也遍历出来
- 用户可控的 key(如表单字段、路由路径、配置项名)可能恰好是保留字,引发不可预测的副作用
Object.create(null) 做了什么?
它让新对象的内部 [[Prototype]] 直接为 null,从源头上清零继承关系。结果是一个没有原型、没有内置方法、也没有隐式行为的对象:
- console.log(obj.toString) → undefined(不是函数,也不报错)
- obj.hasOwnProperty === undefined(真·不存在)
- Object.getPrototypeOf(obj) === null(可验证)
- JSON.stringify(obj) 仍能正常工作,只序列化自有可枚举属性
使用时必须注意的关键点
“干净”带来自由,也意味着放弃默认能力。所有操作需显式处理:
- 判断属性是否存在:用 Object.prototype.hasOwnProperty.call(obj, key),或更现代的 Object.hasOwn(obj, key)(ES2022+)
- 遍历键名:推荐 Object.keys(obj);for...in 在 null 原型下只遍历自身属性,可用但语义不如 keys 明确
- 检查是否为空:Object.keys(obj).length === 0
- 需要 toString 行为?可手动赋值:obj.toString = () => '[object Dict]'
它适合做什么,不适合做什么?
适合场景聚焦在“纯数据映射”:
- 路由表、事件监听器注册表、模块导出映射(如 exports = Object.create(null))
- 配置缓存、AST 节点属性、防污染的沙箱上下文
- 高频 key 查询且 key 名不可控的哈希结构(如用户输入的字段名作键)
不适合替代复杂对象模型或需要丰富原型方法的场景。如果需要 Map 的全部能力(任意类型键、迭代器、size 属性等),应优先选 Map;若需 JSON 兼容、点号访问、轻量级结构,Object.create(null) 仍是不可替代的简洁方案。

















