Object.create(null)是唯一创建真正无原型对象的方式,它不继承Object.prototype的任何方法,可避免原型链污染、属性名冲突及安全风险,但需用key in dict检查键存在、Object.keys遍历且无法使用hasOwnProperty。

Object.create(null) 是唯一能创建真正“无原型”对象的方式,它比 {} 或 new Object() 更干净——没有 toString、hasOwnProperty、constructor 等默认方法,天然规避原型链污染和属性名冲突。
为什么不能用 {} 当字典?
空对象 {} 的 __proto__ 指向 Object.prototype,这意味着:
- 所有继承的方法(如
hasOwnProperty)都可被用户传入的 key 覆盖:dict.hasOwnProperty = 42后,后续调用会出错或行为异常 - 某些 key(如
"toString"、"valueOf")会意外屏蔽原型方法,导致for...in或JSON.stringify(dict)表现异常 - 第三方库或恶意输入可能通过
__proto__或constructor注入属性(尤其在未冻结对象时)
如何安全地初始化和使用 Object.create(null) 字典?
创建后需注意:它不带任何方法,连 hasOwnProperty 都没有,所以所有操作必须显式处理。
- 检查键是否存在 → 改用
key in dict(in操作符不依赖原型) - 避免用
dict.hasOwnProperty(key)—— 它会报TypeError: dict.hasOwnProperty is not a function - 遍历建议用
Object.keys(dict)或for (const key of Object.keys(dict)),不要用for...in(虽此时无继承属性,但语义不清) - 需要类型判断时,优先用
typeof dict[key] !== 'undefined'或直接访问后判断是否=== undefined
常见误用场景与修复示例
以下写法看似合理,实则埋雷:
const dict = Object.create(null); dict.toString = 'hello'; // ✅ 合法,不会触发原型方法 console.log(dict.toString()); // ❌ TypeError: dict.toString is not a function
正确做法是明确区分“数据键”和“逻辑方法”,或封装一层安全访问:
- 若需保留
toString作为数据键 → 接受它不可调用,改用其他名字(如dict['$toString']) - 若需序列化 → 用
JSON.stringify(Object.fromEntries(Object.entries(dict))),或直接JSON.stringify(dict)(现代引擎已支持,但 IE 不行) - 若需合并多个字典 → 用
Object.assign({}, dict1, dict2)不再适用;应手动遍历赋值或用Object.assign(Object.create(null), dict1, dict2)
最易被忽略的一点:Object.create(null) 创建的对象无法被 instanceof 识别,也不能被 Object.prototype.toString.call(dict) 正确分类(返回 [object Object] 而非更精确的标识),如果下游代码依赖这类反射行为,得额外记录类型元信息。

















