基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Object.create(null) 和 new Object() 创建的对象有什么区别?

知识点图片

Object.create(null)new Object()(或者字面量 {})在 JavaScript 中都用于创建对象,但它们之间有着本质的区别,核心差异在于原型链(Prototype Chain)

简单来说:

  • new Object() 创建的是一个带有标准原型链的普通对象。
  • Object.create(null) 创建的是一个绝对纯净的空对象,没有任何原型和内置方法。

以下是详细对比:

1. new Object() (或 {})

当你使用 new Object() 或字面量 {} 创建对象时,这个对象默认会继承 Object.prototype

  • 原型链obj.__proto__ === Object.prototype
  • 自带属性和方法:因为它继承了 Object.prototype,所以它天生自带许多内置方法,例如 toString()valueOf()hasOwnProperty() 等。

示例:

javascript
let obj1 = new Object(); // 等同于 let obj1 = {};

console.log(obj1.toString); // [Function: toString]
console.log(obj1.hasOwnProperty); // [Function: hasOwnProperty]
console.log(obj1.constructor); // [Function: Object]

2. Object.create(null)

Object.create(proto) 方法会使用指定的 proto 对象作为新创建对象的原型。当你传入 null 时,意味着新对象没有原型

  • 原型链:完全没有原型(没有 __proto__ 属性,或者说原型指向 null)。
  • 自带属性和方法:什么都没有。它是一个真正的“空字典”(裸对象),没有任何内置方法。

示例:

javascript
let obj2 = Object.create(null);

console.log(obj2.toString); // undefined
console.log(obj2.hasOwnProperty); // undefined
console.log(obj2.constructor); // undefined
console.log(obj2.__proto__); // undefined

3. 为什么需要 Object.create(null)?(应用场景)

既然什么方法都没有,那为什么要用它呢?主要有以下几个原因:

A. 作为纯粹的字典/哈希映射(Map)

在使用普通对象 {} 存储键值对时,如果键名是用户输入的,可能会与原型链上的属性发生命名冲突

javascript
// 使用普通对象
let counts = {};
let word = "constructor"; 
// 假设你想记录 "constructor" 这个词出现的次数
if (counts[word]) {
    counts[word]++;
} else {
    counts[word] = 1; // 这里会出 bug!
}
// 因为 counts["constructor"] 默认是一个函数,不是 undefined,所以逻辑会出错。

// 使用 Object.create(null)
let pureCounts = Object.create(null);
let word2 = "constructor";
if (pureCounts[word2]) { // undefined,正常进入 else
    pureCounts[word2]++;
} else {
    pureCounts[word2] = 1; // 完美运行
}

注意:在现代 JavaScript 中,如果需要键值对映射,更推荐使用 ES6 的 Map 数据结构,但了解 Object.create(null) 依然很重要。

B. 提升性能(微乎其微但存在)

对于 Object.create(null) 创建的对象,在使用 for...in 循环时,不需要遍历原型链,在检查属性时也不需要去原型链上查找,因此在极端的性能场景下(如大型数据字典),它的运行效率会略高一点。

C. 防止原型污染安全问题

在处理外部传入的不可信数据(如解析 JSON)时,使用 Object.create(null) 可以避免黑客通过 __proto__ 属性进行原型链污染攻击。


4. 总结对比表

特性 new Object(){} Object.create(null)
原型 (Prototype) 指向 Object.prototype 没有原型 (null)
内置方法 有 (toString, hasOwnProperty 等) 无 (完全纯净)
对象类型校验 typeof obj === 'object' typeof obj === 'object'
hasOwnProperty 可以直接调用 obj.hasOwnProperty('x') 会报错!需用 Object.hasOwn(obj, 'x')Object.prototype.hasOwnProperty.call(obj, 'x')
适用场景 普通的对象操作,需要面向对象特性 纯粹的键值对存储(字典),防属性冲突,防原型污染
00:00
00:00