前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库hasOwnProperty 与 in 区分自身属性和原型属性
JavaScript对象与原型

怎么判断一个属性是对象自己的,还是从原型上继承来的?

in 会顺着原型链一路往上找,找到就返回 true;hasOwnProperty 和 Object.hasOwn 只看对象自己身上有没有这个键。要判断「是不是自己的」,现在首选 Object.hasOwn(obj, key)。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#对象与原型
先看核心答案读代码示例
理解线索

查找范围决定结果

  1. in自身找不到就沿原型往上找,一直到 Object.prototype
  2. obj.hasOwnProperty(key)只看自身,但这个方法本身是从原型上继承来的
  3. Object.hasOwn(obj, key)静态方法,只看自身,不依赖对象的原型

hasOwnProperty 是挂在 Object.prototype 上的普通方法,对象没有这个原型或者把它覆盖了,调用就会报错或返回错误结果。

核心回答

先记住这个答案

in 和 hasOwnProperty 的区别在查找范围。'toString' in {} 是 true,因为 in 会沿原型链找到 Object.prototype.toString;({}).hasOwnProperty('toString') 是 false,因为它只看对象自己。判断自有属性,现在推荐用 ES2022 加的 Object.hasOwn(obj, key),它不依赖对象身上的方法,遇到没有原型的对象也不会出错。

  • in 查整条原型链,hasOwn 只查自身
  • 两者判断的都是键在不在,不管值是不是 undefined
  • 无原型对象没有 hasOwnProperty
  • for...in 会遍历继承键

同一个对象,两种判断结果不同

拿一个有原型的对象试一下,区别一眼就能看出来。Object.create(proto) 创建的对象会把 proto 当作原型。

继承属性和值为 undefined 的属性JavaScript
const proto = { shared: 1 }
const obj = Object.create(proto) // obj 的原型是 proto
obj.own = 2
obj.empty = undefined

console.log('shared' in obj) // 原型上有,true
console.log(obj.hasOwnProperty('shared')) // 自己没有,false
console.log(Object.hasOwn(obj, 'own')) // 自己有,true
console.log('empty' in obj, obj.empty !== undefined)
查看输出与解释
true
false
true
true false

shared 定义在原型上,in 能看到,hasOwnProperty 看不到。最后一行说明另一件事:in 和 hasOwn 判断的是「这个键存不存在」,和值是什么无关。属性值是 undefined 时,用 obj.empty !== undefined 会误判成不存在,用 in 或 hasOwn 才准。 所以选哪个取决于你要回答的问题。想知道「读 obj.x 能不能读到东西」,用 in;想知道「这个值是不是这个对象自己存的」,用 Object.hasOwn。

为什么推荐 Object.hasOwn

hasOwnProperty 本身不是语言关键字,它只是 Object.prototype 上的一个方法。对象能调用它,靠的也是原型链。这就带来两个问题。

没有原型的对象调不了
Object.create(null) 常用来做纯净的字典,这种对象没有原型,身上什么方法都没有。写 dict.hasOwnProperty('a') 会直接抛 TypeError,提示 hasOwnProperty 不是一个函数。从 JSON 解析出来的对象不会这样,但一些库和框架内部的映射表会用这种对象。
方法可能被覆盖
对象自己如果有一个叫 hasOwnProperty 的键,比如后端返回的数据里恰好有这个字段,调用时拿到的就是那个值,不是原生方法。以前的稳妥写法是借用原型上的方法:Object.prototype.hasOwnProperty.call(obj, key)。Object.hasOwn(obj, key) 做的就是这件事,写起来更短,ESLint 的 prefer-object-has-own 规则也会建议替换。

遍历时怎么排除继承属性

for...in 会把原型链上可枚举的属性也遍历出来。比如用 Object.create(defaults) 做了一个配置对象,defaults 里的字段都会出现在 for...in 里。老代码里常见的写法是在循环里加一句 if (!Object.hasOwn(obj, key)) continue。

更简单的做法是直接换成 Object.keys(obj),它只返回自身可枚举的字符串键,不用再过滤。要包含不可枚举的键,用 Object.getOwnPropertyNames;要连 Symbol 键也拿到,用 Reflect.ownKeys。这几个都只看自身,不碰原型。

回答前,多想一步

容易答错的地方

用 in 判断对象自己有没有某个属性
'toString' in obj 对几乎所有普通对象都是 true,所以 in 不能用来做「自有属性」判断。比如用对象当计数表,'constructor' in counts 会返回 true,逻辑就出错了。
用 obj.key !== undefined 代替存在性判断
属性存在但值是 undefined 时,这种写法会判断成不存在;属性在原型上时,它又会判断成存在。它判断的是「读出来的值」,不是「键在哪」。
认为 hasOwnProperty 在任何对象上都能调
没有原型的对象、覆盖了同名键的对象都会让它失效。不确定对象来源时直接用 Object.hasOwn。
试着用自己的话回答

面试官还会怎么问?

不可枚举的自有属性,hasOwn 会返回什么?

返回 true。hasOwn 只管键是不是自己的,不管 enumerable。比如数组的 length 不可枚举,Object.hasOwn([], 'length') 是 true,但 Object.keys([]) 里没有它。

Object.hasOwn 不支持的老环境怎么办?

用 Object.prototype.hasOwnProperty.call(obj, key),效果一样。也可以通过 core-js 之类的 polyfill 补上 Object.hasOwn。

想知道属性具体在原型链的哪一层,怎么找?

从对象本身开始,每层用 Object.hasOwn 检查一次,没有就用 Object.getPrototypeOf 取上一层原型继续找,直到原型是 null。in 只能告诉你有没有,给不出层级。

从一道题,走向一组知识

把知识连起来

对象与原型

属性设成 enumerable:false 后,for...in 和 Object.keys 还能遍历到吗?

Object.keys 和 for...in 只列可枚举属性,但 hasOwn 对不可枚举的自有属性也返回 true。

对象与原型

读取一个对象属性时,JavaScript 是按什么顺序在原型链上找的?

in 的查找顺序就是原型链属性查找的顺序,看懂那道题就知道 in 为什么能看到继承属性。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Object.hasOwn()

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同一个对象,两种判断结果不同
  3. 为什么推荐 Object.hasOwn
  4. 遍历时怎么排除继承属性
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑