← 返回题目列表

Object.hasOwn 和 hasOwnProperty 有什么区别?

中等 第 28 / 28 题 更新于 2026/07/29
ES6Object属性判断

简化版

Object.hasOwn(obj, key) 用于判断某个属性是不是对象自身属性。它比 obj.hasOwnProperty(key) 更安全,因为对象可能没有原型,或者自己的属性名刚好覆盖了 hasOwnProperty

它不会判断继承属性,也不会关心属性是否可枚举;只要是自有属性,就返回 true

详细版

const obj = Object.create(null);
obj.name = "Ada";

// obj.hasOwnProperty("name"); // TypeError
Object.hasOwn(obj, "name"); // true

覆盖方法名的情况:

const user = {
  hasOwnProperty: false,
  id: 1
};

Object.hasOwn(user, "id"); // true

in 的区别:

const proto = { inherited: true };
const obj = Object.create(proto);
obj.own = true;

"inherited" in obj; // true
Object.hasOwn(obj, "inherited"); // false

完整版教学

一、属性判断先区分自身和继承

JavaScript 对象会沿原型链查找属性。

obj -> prototype -> prototype -> null

in 会看整条链,Object.hasOwn 只看对象自身。

面试问 hasOwn,本质是在问你有没有把“属性可访问”和“属性属于自己”分开。

二、Object.hasOwn 的基本用法

const obj = { a: 1 };

console.log(Object.hasOwn(obj, "a")); // true
console.log(Object.hasOwn(obj, "toString")); // false

它是静态方法,不依赖对象自身是否继承了某个方法。

三、为什么不直接用 obj.hasOwnProperty

普通对象一般可用:

({ a: 1 }).hasOwnProperty("a"); // true

但有两个风险。

第一,对象可能没有原型:

const dict = Object.create(null);
dict.a = 1;

第二,对象可能覆盖同名属性:

const obj = { hasOwnProperty: "not a function", a: 1 };

这时 Object.hasOwn(obj, "a") 更稳。

四、和 in 运算符的区别

const proto = { role: "admin" };
const user = Object.create(proto);
user.name = "Ada";

console.log("role" in user); // true
console.log(Object.hasOwn(user, "role")); // false

in 适合判断属性能否访问到,Object.hasOwn 适合判断是否为对象自己的数据。

五、不可枚举属性也算自有属性

const obj = {};
Object.defineProperty(obj, "hidden", {
  value: 1,
  enumerable: false
});

Object.keys(obj); // []
Object.hasOwn(obj, "hidden"); // true

自有和可枚举是两个维度,不要混在一起。

维度判断方式
是否可访问key in obj
是否自有Object.hasOwn(obj, key)
是否可枚举propertyIsEnumerable 或遍历 API

六、适合处理字典对象和外部输入

处理接口返回、配置对象、字典表时,属性名可能不可控。

function getOwnValue(obj, key) {
  if (Object.hasOwn(obj, key)) {
    return obj[key];
  }
  return undefined;
}

这比直接调用 obj.hasOwnProperty 更少假设。

七、常见误区与追问

  • 误区:inObject.hasOwn 等价。 in 会检查原型链,hasOwn 只检查自身。
  • 误区:不可枚举属性不是自有属性。 可枚举和自有是不同维度。
  • 误区:所有对象都能调用 hasOwnProperty。 Object.create(null) 创建的对象没有这个方法。
  • 误区:对象自己的 hasOwnProperty 一定是函数。 它可能被业务字段覆盖。
  • 追问:为什么处理外部输入时 hasOwn 更安全? 因为它不依赖对象原型和对象上的同名方法。
  • 追问:Object.hasOwn 会不会触发 getter? 判断属性存在性本身不需要读取属性值。

八、加强记忆

记忆对比:

key in obj             -> own or inherited
Object.hasOwn(obj,key) -> own only
Object.keys(obj)       -> own enumerable string keys

回答时先讲原型链,再给 Object.create(null) 和同名覆盖两个例子,最后补“自有不等于可枚举”,这题就稳了。