在 JavaScript 中,使用 Object.create(null)
和 {}
创建的对象有以下核心区别:
1. 原型链的差异
创建方式 | 原型链([[Prototype]] ) | 继承关系 |
---|---|---|
const obj = {} | 继承自 Object.prototype | 拥有 Object 的原型方法 |
const obj = Object.create(null) | 原型链为 null | 无任何继承 |
示例代码
const objLiteral = {};
const objNullProto = Object.create(null);console.log(objLiteral.toString); // ƒ toString() { [native code] }
console.log(objNullProto.toString); // undefined(无原型链)
2. 内置方法的存在性
-
{}
创建的对象:
继承Object.prototype
的方法,如toString
、hasOwnProperty
、valueOf
等。const obj = {}; console.log("toString" in obj); // true(来自原型链)
-
Object.create(null)
创建的对象:
完全纯净,不包含任何继承方法。const obj = Object.create(null); console.log("toString" in obj); // false
3. 适用场景
使用 {}
的场景
- 需要利用
Object
的原型方法(如obj.hasOwnProperty()
)。 - 需要与其他代码或库交互,依赖对象的标准行为。
- 快速创建普通对象,无需特殊处理原型链。
使用 Object.create(null)
的场景
-
作为纯字典(键值对):
避免原型链属性污染(如toString
、constructor
等可能被误覆盖)。const dict = Object.create(null); dict.key = "value"; console.log("toString" in dict); // false(不会被意外覆盖)
-
性能优化:
无原型链的对象在某些引擎中访问速度更快(极少情况需实测验证)。 -
特殊用途:
实现更安全的属性存储(如JSON.stringify(obj)
时不会包含原型链上的属性)。
4. 其他差异
特性 | {} | Object.create(null) |
---|---|---|
instanceof Object | true | false (无 Object 原型链) |
属性枚举 | 可能包含原型链属性(需用 hasOwnProperty 过滤) | 仅自身属性 |
内存占用 | 稍高(包含原型链引用) | 更低(无原型链) |
示例对比
// 使用 {} 创建的对象
const obj1 = {};
console.log(obj1.constructor); // ƒ Object() { [native code] }(来自原型链)// 使用 Object.create(null) 创建的对象
const obj2 = Object.create(null);
console.log(obj2.constructor); // undefined// 安全存储键值对
const safeDict = Object.create(null);
safeDict.toString = "自定义值"; // 无需担心覆盖原型方法
console.log(safeDict.toString); // "自定义值"(而非方法)
总结
-
{}
:
适合大多数场景,拥有标准对象的行为和原型方法,方便与其他代码交互。 -
Object.create(null)
:
适合需要完全纯净、无原型干扰的场景(如字典、低耦合数据存储),但需手动实现原型方法(如hasOwnProperty
的替代方案)。