hasOwnProperty 无法实现真正的深度对比,因其仅判断属性是否为对象自有,不比较值、不递归、不处理嵌套结构;它在深度对比中的核心作用是过滤继承属性,避免原型方法干扰,常与递归和类型判断结合使用。

直接用 hasOwnProperty 无法实现真正的深度对比,它只判断对象自身是否拥有某个属性(不查原型链),但可以作为深度对比中“属性存在性检查”的一个基础工具。要实现简单可靠的深度对比,需结合递归、类型判断和 hasOwnProperty 排除继承属性干扰。
为什么不能只靠 hasOwnProperty?
hasOwnProperty 只回答“这个 key 是不是对象自己定义的”,不比较值、不递归、不处理数组或嵌套对象。比如两个结构相同但属性来自原型的对象,hasOwnProperty 结果一样,但实际内容可能不同。
用 hasOwnProperty 过滤掉继承属性
在遍历对象时,必须跳过原型上的属性,否则会把 toString、valueOf 等方法也纳入对比,导致误判。这是 hasOwnProperty 在深度对比中最关键的作用:
- 遍历对象所有 key 时,先用
obj.hasOwnProperty(key)确保该 key 属于实例本身 - 忽略
for...in默认包含的原型属性 - 避免因原型链污染或扩展导致的对比错误
基础深度对比函数(含 hasOwnProperty)
以下是一个轻量、可读性强的实现,支持普通对象和原始值,使用 hasOwnProperty 保证只比自有属性:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (typeof a !== 'object' || typeof b !== 'object') return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) {
// 关键:确保是自有属性,排除原型干扰
if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) continue;
if (!deepEqual(a[key], b[key])) return false;
}
return true;
}
注意:Object.keys() 本身只返回自有可枚举属性,已隐含 hasOwnProperty 逻辑,所以严格来说上面的 hasOwnProperty 检查是冗余的;但显式写出能更清晰表达意图,尤其在手动用 for...in 时必不可少。
更稳妥的写法(兼容 for...in 场景)
如果选择用 for...in 遍历(例如需要兼容旧环境或特殊枚举控制),hasOwnProperty 就不可省略:
for (let key in a) {
if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) continue;
if (!deepEqual(a[key], b[key])) return false;
}
同时建议补充对数组、Date、RegExp 等类型的单独处理,否则它们会被当作普通对象递归,结果可能不符合预期。

















