Object.create(null)创建的对象没有toString、hasOwnProperty等方法,因其原型为null,不继承Object.prototype;适用于需绝对纯净键值容器的场景,如哈希表、事件存储、JSON Schema校验上下文等。

为什么 Object.create(null) 创建的对象没有 toString、hasOwnProperty 等方法
因为它的原型链被彻底切断了——它不继承自 Object.prototype,而所有默认方法(如 toString、valueOf、hasOwnProperty)都来自那里。普通对象用 {} 或 Object.create({}) 创建时,原型是 Object.prototype;但 Object.create(null) 的原型是 null,查不到任何内置方法。
什么时候该用 Object.create(null) 而不是 {}
典型场景是需要绝对干净的键值容器,比如实现哈希表、缓存映射、或作为事件监听器的存储对象。一旦你担心用户传入的 key 恰好撞上 constructor、toString 这类属性名,就会引发意外覆盖或原型链污染。
- 用作 Map 替代品且 key 可能为任意字符串(包括
"hasOwnProperty")时必须用Object.create(null) - 做 JSON Schema 校验上下文、AST 节点属性集等元数据容器时,避免被原型方法干扰
- 写 polyfill 或底层工具函数(如
isPlainObject)时,需排除原型干扰
用了 Object.create(null) 后哪些操作会出错
直接调用原型方法会报 TypeError: xxx is not a function,比如:
const obj = Object.create(null);
obj.toString(); // TypeError
obj.hasOwnProperty('a'); // TypeError
解决方式不是“补回去”,而是改用更安全的替代方案:
- 检查属性存在:用
Object.prototype.hasOwnProperty.call(obj, key)或key in obj(注意后者会查原型链,但此时原型是null,所以等价) - 转字符串:用
JSON.stringify(obj)或String(obj)(后者会返回[object Object],但不会报错) - 枚举属性:仍可用
Object.keys(obj)、for...in(因无原型属性,二者行为一致)
Object.create(null) 和 Map 该怎么选
如果只是存键值对,优先考虑 Map:它天生支持任意类型 key、保持插入顺序、有明确的 size 和迭代接口。但 Object.create(null) 在以下情况仍有不可替代性:
- 需要与旧代码或 JSON 兼容(
Map不能直接JSON.stringify) - 性能敏感场景(极大量短生命周期对象,
Object.create(null)初始化比new Map()略快) - 必须用点号或方括号语法(
obj.key/obj[key]),而不想封装一层代理
别为了“纯净”硬套 Object.create(null)——如果不需要防御原型污染,{} 更自然;如果需要强类型和丰富方法,Map 更稳妥。真正关键的是理解原型链断在哪、以及你是否真的在和那条链博弈。

















