in 检查属性是否可访问(含原型链),hasOwnProperty 仅检查对象自身属性;Object.hasOwn 是更安全的现代替代方案,推荐优先使用。

本质区别就一点:in 查整个原型链,hasOwnProperty 只查对象自己身上有没有这个属性名。
in 检查的是“能不能访问到”
只要属性名出现在对象自身、或者任意一级原型上,in 就返回 true。它不关心属性是哪来的,只看最终能否通过点号或方括号取到值。
- 对数组用
'0' in arr,检查的是索引是否存在,不是元素值是否为真 - 属性值是
undefined,'key' in obj依然为 true - 遇到
null或undefined会直接报错,必须确保左操作数是对象
hasOwnProperty 检查的是“是不是我定义的”
hasOwnProperty 是 Object 原型上的方法,它只认对象自己 直接挂上去 的属性,完全无视原型链。
- 写法必须是
obj.hasOwnProperty('key'),不能省略括号调用 - 如果对象是
Object.create(null)创建的,它没有原型,调用该方法会报错 - 推荐写法:
Object.prototype.hasOwnProperty.call(obj, 'key'),避免对象自己重写了该方法
ES2022 起更安全的替代方案
Object.hasOwn(obj, 'key') 是官方推荐的新 API,它和 hasOwnProperty 行为一致,但不用怕被覆盖、也不用 call 绑定,可直接使用:
-
Object.hasOwn(obj, 'key')—— 安全、简洁、语义明确 - 在 Node.js 16.9+、Chrome 93+、Firefox 91+ 等现代环境中已稳定支持
- 对于老旧环境,可用 polyfill 或回退到 call 方式
怎么避免误判原型属性
关键不是“避免用 in”,而是根据目的选对工具:
- 遍历对象时过滤掉继承属性(比如
for...in循环),一律用Object.hasOwn或hasOwnProperty做守门员 - 判断某个方法是否可用(如
'addEventListener' in window),用 in 更合理——你关心的是“能不能调”,不管它在哪定义 - 配置类对象、纯数据容器,优先用
Object.create(null)创建,从源头切断原型链干扰 - 不要往
Object.prototype上添加属性,这是污染全局原型链的高危操作


















