Object.create(null) 创建的对象无原型,{} 继承 Object.prototype;前者无法调用 toString 等方法,需显式委托,适用于纯键值映射等需避免原型干扰的场景。

Object.create(null) 创建的对象没有原型,{} 创建的对象默认继承 Object.prototype。
原型链起点不同
{} 是 Object 构造函数的语法糖,等价于 Object.create(Object.prototype),其 __proto__ 指向 Object.prototype,因此能直接调用 toString、hasOwnProperty、valueOf 等方法。
Object.create(null) 创建的对象 __proto__ 为 null,原型链在创建时即被截断,不挂载任何继承属性或方法。
属性遍历行为差异
使用 for...in 遍历时:
• {} 对象会遍历自身 + 原型链上的可枚举属性(比如不小心定义了 toString 就可能覆盖原型方法,或被原型方法干扰)
• Object.create(null) 对象只遍历自身属性,无需额外用 hasOwnProperty 过滤
• Object.keys()、Object.getOwnPropertyNames() 在两者上行为一致,都只返回自有属性
方法调用需显式委托
因为缺失原型,Object.create(null) 对象无法直接调用内置方法:
• obj.toString() → TypeError
• obj.hasOwnProperty(key) → TypeError
• 正确写法是:Object.prototype.toString.call(obj) 或 Object.prototype.hasOwnProperty.call(obj, key)
典型适用场景
• 纯键值映射容器:如 i18n 语言包、路由表、配置缓存,避免键名(如 "toString"、"constructor")与原型方法冲突
• 防污染字典结构:不希望外部输入意外覆盖或触发原型方法
• Proxy 沙箱基础对象:配合 Proxy 实现完全可控的 get/set 行为,无隐式原型干扰
• 高频属性读写场景:省去原型链查找开销(虽微小,但在极致优化中有效)
不复杂但容易忽略:选哪个不是看“更高级”,而是看是否需要原型能力——要便利性选 {},要确定性选 Object.create(null)。


















