jstips 系列第 10 期:徹底掌握 JavaScript 物件屬性檢查——`in` 運算子與 `hasOwnProperty` 的深度差異
教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载本文對應 jstips 倉庫第 10 期技巧繁體中文版_posts/zh_TW/javascript/2016-01-10-check-if-a-property-is-in-a-object.md另有英文原版、簡體中文版與西班牙語版。本篇將從最常見的直覺寫法出發完整對比 JavaScript 中檢查物件屬性是否存在的兩大原生手段——in運算子與Object.prototype.hasOwnProperty剖析兩者在「自身屬性」與「原型鏈繼承屬性」上的核心差異並結合本倉庫其他技巧如無原型物件、屬性挑選等說明何時該用哪一種幫你寫出正確、高效且無隱患的屬性存在性判斷。一、最常見的寫法if (myObject.name)及其陷阱檢查某個屬性是否存在於物件中許多開發者的第一反應是直接讀取值並判斷真偽var myObject { name: tips_js }; if (myObject.name) { ... }這段寫法「能用」但它其實隱藏著一個關鍵缺陷它判斷的是屬性的「真值truthy」狀態而不是屬性的「存在與否」。JavaScript 中所有 falsy 值——0、空字串、false、null、undefined、NaN——都會讓這個條件判斷失敗即使屬性本身確實存在var config { retries: 0, // 屬性存在但值為 falsy label: , // 屬性存在但值為 falsy enabled: false // 屬性存在但值為 falsy }; if (config.retries) { /* 不會執行即使 retries 已定義且等於 0 */ } if (config.label) { /* 不會執行即使 label 已定義為空字串 */ }換言之只要屬性的值恰好落在 falsy 集合裡if (obj.prop)就會誤判為「屬性不存在」。若要精確回答「這個 key 到底存不存在」JavaScript 提供了兩個原生方法in運算子與Object.hasOwnProperty。任何繼承自Object的物件都可以使用這兩種方式——這是本技巧tip 10的核心內容也與倉庫中第 5 期「undefined與null的差異」所討論的 falsy/truthy 語義一脈相承。二、兩種原生方法in運算子與hasOwnProperty2.1in運算子in是 JavaScript 的內建運算子語法為propertyName in object。它會沿著物件的整個原型鏈向上查找只要在自身屬性或任何一層繼承屬性中找到該 key就回傳truevar myObject { name: tips_js }; name in myObject; // true自身屬性 valueOf in myObject; // true繼承自原型鏈注意in運算子的左側必須是字串形式的屬性名稱或會被轉換為字串的表達式且當右側不是物件時會拋出TypeError。2.2Object.prototype.hasOwnPropertyhasOwnProperty是定義在Object.prototype上的方法任何普通物件都能直接呼叫。它只檢查自身屬性不往上追溯原型鏈var myObject { name: tips_js }; myObject.hasOwnProperty(name); // true myObject.hasOwnProperty(valueOf); // falsevalueOf 繼承自原型鏈2.3 兩者的本質差異原文用一段對比清晰地呈現了兩者的差別var myObject { name: tips_js }; myObject.hasOwnProperty(name); // true name in myObject; // true myObject.hasOwnProperty(valueOf); // false, valueOf 繼承自原型鏈結 valueOf in myObject; // true兩者不同的地方在於確認屬性的深度不同。換句話說如果 key 直接存在於物件本身hasOwnProperty才會回傳true而in運算子無法分辨屬性是建立在物件上還是繼承自原型鏈——只要是沿著原型鏈可達的屬性in一律回答「存在」。這個差異在實務上非常關鍵任何普通物件都繼承了Object.prototype上的方法例如constructor、toString、valueOf、hasOwnProperty、isPrototypeOf等。因此toString in {}→true繼承而來{}.hasOwnProperty(toString)→false並非自身屬性三、原型鏈情境下的對比構造函數範例原文給出了第二組更貼近真實開發的範例透過構造函數與prototype展示繼承屬性的行為var myFunc function() { this.name tips_js; // 建立「自身屬性」 }; myFunc.prototype.age 10 days; // 在原型上建立「繼承屬性」 var user new myFunc(); user.hasOwnProperty(name); // true user.hasOwnProperty(age); // false, 因為 age 繼承自原型鏈結這段程式碼說明了三件事在構造函數內用this.name ...賦值的屬性會成為每個實例的自身屬性因此user.hasOwnProperty(name)為true掛在myFunc.prototype上的age會被所有實例透過原型鏈「看到」但它不是實例的自身屬性所以user.hasOwnProperty(age)為false若改用in運算子age in user則會回傳true——因為in會沿著user → myFunc.prototype → Object.prototype這條鏈逐一查找。由此可以歸納出選擇原則判斷目標推薦方式行為只關心「自身屬性」是否存在例如資料校驗、白名單過濾Object.prototype.hasOwnProperty不追溯原型鏈關心「可讀取到該屬性」含繼承屬性例如特性偵測in運算子沿原型鏈完整查找四、現代進化Object.hasOwn與無原型物件4.1Object.hasOwnES2022hasOwnProperty有一個已知弱點如果物件本身被賦予了名為hasOwnProperty的屬性例如var o { hasOwnProperty: null }直接呼叫o.hasOwnProperty(...)就會失敗或行為異常。ES2022 提供了更穩健的靜態方法Object.hasOwn(obj, prop)它不依賴物件自身的同名屬性是取代hasOwnProperty的推薦寫法Object.hasOwn({ name: tips_js }, name); // true Object.hasOwn({ name: tips_js }, valueOf); // false4.2Object.create(null)完全繞過原型鏈當你需要一個「純資料容器」、不想被任何繼承屬性干擾時可以建立無原型物件。本倉庫第 73 期「無副作用雜湊表Hash maps without side effects」正是這個主題的代表透過Object.create(null)我們明確指定null作為其原型。因此它完全沒有任何屬性——連constructor、toString、hasOwnProperty等都沒有——你可以放心地在資料結構中使用這些 key 當作鍵名。該文同時展示了在遍歷雜湊表時使用hasOwnProperty來排除繼承屬性的典型寫法if (dirtyMap.hasOwnProperty(key)) { // 檢查以避開繼承屬性 // 僅處理自身屬性 }這與本期技巧正好互為表裡當你面對普通物件帶有Object.prototype繼承鏈時必須用hasOwnProperty/Object.hasOwn或in來明確控制檢查深度而Object.create(null)則從根源上消除繼承屬性的干擾。五、倉庫中的實際應用佐證jstips 倉庫內多篇技巧都在真實使用這兩種檢查方式可作為最佳實踐的參考第 70 期「挑選與排除物件屬性」其pick函式用k in obj判斷 key 是否存在於目標物件再決定是否取出該屬性function pick(obj, keys) { return keys.map(k k in obj ? {[k]: obj[k]} : {}) .reduce((res, o) Object.assign(res, o), {}); }這裡使用in而非hasOwnProperty是因為pick的語義是「取出該物件含繼承鏈可讀到的屬性」與in的深度行為一致。第 73 期「無副作用雜湊表」如上所述在for...in這類會遍歷繼承屬性的語法中用hasOwnProperty過濾掉非自身屬性是經典的安全寫法。第 39 期「進階屬性Advanced Properties」講解Object.defineProperty定義value、writable、enumerable、configurable等屬性描述元。當屬性被設為enumerable: false時for...in不會列出它但in與hasOwnProperty仍會正確回報其存在——這提醒我們屬性是否「可列舉」與屬性是否「存在」是兩個獨立維度。六、實務選擇建議與常見錯誤總結綜合原文與倉庫內相關技巧給出以下決策指引判斷「是否存在」而非「是否 truthy」當屬性值可能為0、、false、null、undefined、NaN時if (obj.prop)必然誤判。此時改用in或hasOwnProperty。只要自身屬性如表單欄位校驗、資料欄位白名單、for...in過濾優先使用Object.hasOwn(obj, prop)現代環境或obj.hasOwnProperty(prop)相容舊環境。需要沿原型鏈查找如特性偵測、判斷某方法是否「可被呼叫」使用in運算子。避免呼叫被覆寫的hasOwnProperty若物件可能帶有同名自訂屬性改用Object.hasOwn或Object.prototype.hasOwnProperty.call(obj, key)。純資料容器需要徹底不受繼承屬性干擾時使用Object.create(null)建立無原型物件參見第 73 期。常見錯誤的根源在於把「屬性值為 falsy」誤當成「屬性不存在」以及把「屬性可沿原型鏈讀取」誤當成「屬性為自身所有」。釐清in與hasOwnProperty的深度差異後這兩類問題都能迎刃而解——這正是本期 jstips 技巧tip 10要傳達的核心價值。七、延伸閱讀第 5 期「undefined與null的差異」falsy 值語義與typeof檢查的完整說明第 73 期「無副作用雜湊表」Object.create(null)與hasOwnProperty的實戰組合第 70 期「挑選與排除物件屬性」in運算子在屬性挑選工具中的應用第 39 期「進階屬性」屬性描述元與可列舉性的深入講解POST_TEMPLATE.mdjstips 文章格式範本可了解本期技巧的標準結構赞分享教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载相关推荐jstips 第 10 期检查对象属性是否存在的正确姿势 —— in 操作符与 hasOwnProperty 深度对比jstips 第 10 期检查对象属性是否存在的正确姿势 —— in 操作符与 hasOwnProperty 深度对比 导读 在 JavaScript 日常开教程jstips 技巧 10 深度解读用 in 与 hasOwnProperty 正确检查 JavaScript 对象属性是否存在jstips 技巧 10 深度解读用 in 与 hasOwnProperty 正确检查 JavaScript 对象属性是否存在 导读 在 JavaScrip教程如何看懂 video-compress-cj 压缩质量调优高、中、低三档背后的码率缩放原理如何看懂 video compress cj 压缩质量调优高、中、低三档背后的码率缩放原理 video compress cj 是一款基于硬件编解码 API教程上一篇Apache JMeter 完全技术指南性能测试、安装运行与源码构建实战下一篇WebMCP 实战案例拆解电商导购、创意设计与代码评审中 AI Agent 的 3 大应用场景创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

.NET Core 8 CORS配置指南:从原理到避坑实践

.NET Core 8 CORS配置指南:从原理到避坑实践

1. 为什么.NET Core 8里的CORS还是这么容易踩坑前后端分离已经成为标配,前端跑在localhost:5173,后端跑在localhost:5000,接口一调就报错。浏览器控制台红通通一片:Access to XMLHttpRequest at http://localhost:5000/api/values…

2026/10/9 2:42:43 阅读更多 →
Windows 11与Ubuntu双系统互传文件全攻略:5种方案详解

Windows 11与Ubuntu双系统互传文件全攻略:5种方案详解

如果你的电脑装了Windows 11和Ubuntu Linux双系统,你一定遇到过这种场景:在Windows里下了一个安装包,重启到Ubuntu发现还得再下载一遍;在Ubuntu里渲完的视频,想拷到Windows这边剪辑,U盘插来插去、格式还不认…

2026/10/9 2:42:43 阅读更多 →
磐时出席 2026中国汽车工程学会底盘集成技术分会学术年会

磐时出席 2026中国汽车工程学会底盘集成技术分会学术年会

让智能底盘的“安全兜底”被认真看见 9月20日-22日,由先进越野系统技术全国重点实验室、中国汽车工程学会越野车技术分会及底盘集成技术分会联合主办的2026中国汽车工程学会越野车技术分会第十八届学术年会暨2026先进越野系统科学与技术年会、2026中国汽车工程学会…

2026/10/9 2:41:42 阅读更多 →

最新新闻

基于Golang的分布式资产管理系统:架构设计与实践

基于Golang的分布式资产管理系统:架构设计与实践

简介:这套基于Go语言构建的分布式综合资产管理系统毕业设计资源,面向网络安全红队、SRC团队以及正在开展相关课题的高校学生。系统以资产发现、漏洞扫描、资产管理、任务调度与报告生成为核心,采用PostgreSQL存储数据、NSQ消息队列分发任务、…

2026/10/9 3:14:00 阅读更多 →
CC2530 Zigbee组网实操指南:从烧录到213节点稳定运行

CC2530 Zigbee组网实操指南:从烧录到213节点稳定运行

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 3:14:00 阅读更多 →
C++ SOCKET编程:从同步阻塞到异步非阻塞select模型实现多客户端服务端

C++ SOCKET编程:从同步阻塞到异步非阻塞select模型实现多客户端服务端

1. 同步阻塞与异步非阻塞的本质差异:先搞懂服务端为什么难写前阵子有个刚转C的同事跑来问我:为什么自己写的SOCKET服务端,第一个客户端连上来之后,第二个客户端就一直连不上?我一听就知道,这是掉进了同步阻…

2026/10/9 3:14:00 阅读更多 →
区块链走向价值互联网基础设施:从共识账本到溯源落地的实践思考

区块链走向价值互联网基础设施:从共识账本到溯源落地的实践思考

聊区块链这事,绕不开“价值互联网”这个词。我在这个圈子里前前后后折腾过公链、联盟链、溯源存证和数字资产协议,最大的体感是:区块链真正在变的位置,不是链本身跑得有多快,而是它正在从一群技术理想主义者的实验品&a…

2026/10/9 3:14:00 阅读更多 →
Navicat Premium 12 免安装版全拆解:辨真伪、修报错、转配置

Navicat Premium 12 免安装版全拆解:辨真伪、修报错、转配置

简介:Navicat Premium 12免安装版是一套面向数据库开发与运维人员的多数据库管理工具,支持从单一界面连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite,并兼容阿里云、腾讯云、华为云、Amazon RDS 与 Azure 等主流云…

2026/10/9 3:14:00 阅读更多 →
RK平台UAC1+CDC复合设备:legacy驱动开机即枚举方案

RK平台UAC1+CDC复合设备:legacy驱动开机即枚举方案

简介:这份资源面向嵌入式Linux与Android底层驱动开发者,提供基于Rockchip平台实现的UAC与CDC串口复合设备驱动方案,解决设备开机后需依赖配置脚本才能枚举为USB音频与串口的问题。驱动采用legacy方式,Linux下无需设置usb_gadget&a…

2026/10/9 3:12:59 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →