核心区别在于in检查整个原型链,hasOwnProperty只查对象自身;现代应优先用Object.hasOwn()替代hasOwnProperty,避免原型污染和null原型问题,for...in遍历时必须用Object.hasOwn过滤。
核心区别就一条:in 查整个原型链,hasOwnProperty 只查对象自己身上有没有这个键名。选哪个,取决于你真正想确认的是什么——是“能不能访问到”,还是“是不是我定义的”。
当你关心的是属性是否可被调用或读取(比如判断 obj.method 是否可用),in 是最自然的选择。它不触发 getter,不依赖属性值,只看键名是否存在整个继承链上。
'key' in obj 直观表达意图toString、push)0 in arr),不是元素真假值undefined 时仍返回 true
现代开发中,检查自有属性应默认走 Object.hasOwn(obj, 'key')。它解决了老式 hasOwnProperty 的两个硬伤:怕被覆盖、怕没原型。
obj.hasOwnProperty = null 失效Object.create(null) 创建的对象用属性值做存在性判断,逻辑上就是错的。哪怕看起来能跑通,也埋下隐患。
立即学习“Java免费学习笔记(深入)”;
obj.key !== undefined:值本身是 undefined 就会漏判obj.key != null:把 0、false、'' 全当“不存在”Object.keys(obj).includes('key'):每次循环新建数组,性能差;且漏掉不可枚举属性obj.hasOwnProperty('key'):对象原型被篡改或为 null 原型时会报错for...in 本身就会遍历原型链,所以必须加守门逻辑。这不是可选项,而是必要操作。
for (const key in obj) { if (Object.hasOwn(obj, key)) { /* 处理自有属性 */ } }
Object.keys(obj) 配合 for...of 更轻量Object.prototype 添加方法,这是污染全局、引发遍历干扰的根源