Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
JavaScript如何用Object.hasOwn替代in操作符_创想鸟

JavaScript如何用Object.hasOwn替代in操作符

object.hasown 更安全精确检查对象自身属性,避免 in 操作符检查原型链的问题。1. in 操作符会检查对象自身及原型链上的属性,可能导致意外结果;2. 传统用法使用 object.prototype.hasownproperty.call 避免原型链干扰,但写法冗长且存在被覆盖风险;3. object.hasown 是静态方法,直接挂载于 object,语法简洁且更安全;4. 在遍历对象属性时,若仅需处理自身属性,应配合 object.hasown 过滤继承属性;5. object.hasown 不会受对象自身 hasownproperty 属性覆盖影响,确保调用安全;6. in 操作符仍适用于需检查属性是否存在于对象或原型链任意位置的场景。

JavaScript如何用Object.hasOwn替代in操作符

Object.hasOwn 提供了一种更安全、更精确的方式来检查对象是否拥有自己的属性,它避免了 in 操作符会检查原型链的潜在问题,让你的代码意图更明确,也更健壮。

JavaScript如何用Object.hasOwn替代in操作符

解决方案

在JavaScript中,判断一个对象是否包含某个属性,我们经常会用到 in 操作符。它确实很方便,比如 propertyName in object 就能告诉你这个属性是否存在。但问题来了,in 操作符不仅会检查对象自身的属性,它还会沿着原型链向上查找。这意味着,如果一个属性不在对象本身,但在它的原型链上存在,in 也会返回 true。这在某些场景下可能会导致意想不到的行为,甚至是bug。

举个例子:

立即学习“Java免费学习笔记(深入)”;

JavaScript如何用Object.hasOwn替代in操作符

const myObject = {  name: 'Alice'};const inheritedObject = Object.create(myObject);inheritedObject.age = 30;console.log('name' in inheritedObject); // true (name是继承的)console.log('age' in inheritedObject);  // true (age是自己的)console.log('toString' in inheritedObject); // true (toString是Object.prototype上的)

为了解决这个问题,我们通常会使用 Object.prototype.hasOwnProperty.call(object, propertyName)。这个方法只检查对象自身是否拥有某个属性,不考虑原型链。虽然它有效,但写法上总觉得有点冗长,而且 hasOwnProperty 本身也可能被对象上的同名属性覆盖,虽然这种情况不常见,但理论上存在风险。

Object.hasOwn 就是为了解决这些痛点而生的。它是一个静态方法,直接挂载在 Object 上,用法简洁明了:Object.hasOwn(object, propertyName)。它和 Object.prototype.hasOwnProperty.call 的行为完全一致,只检查对象自身的属性,但更安全、更易读。

JavaScript如何用Object.hasOwn替代in操作符

const myObject = {  name: 'Alice'};const inheritedObject = Object.create(myObject);inheritedObject.age = 30;console.log(Object.hasOwn(inheritedObject, 'name')); // false (name是继承的,不是自己的)console.log(Object.hasOwn(inheritedObject, 'age'));  // true (age是自己的)console.log(Object.hasOwn(inheritedObject, 'toString')); // false (toString是原型链上的)

你看,代码是不是一下子清晰了很多?当你的意图就是“我只想知道这个属性是不是对象自己的”,那么 Object.hasOwn 绝对是首选。它避免了原型链的干扰,让你的逻辑更严谨。

为什么 in 操作符在某些场景下会带来麻烦?

in 操作符的“麻烦”之处,主要源于它对原型链的遍历特性。在很多时候,我们关心的是一个对象“自己”有什么属性,而不是它通过继承“拥有”什么属性。这种混淆,尤其在处理来自外部的、结构不确定的数据时,很容易引发问题。

想象一下,你正在遍历一个对象的属性,比如使用 for...in 循环(虽然现在更推荐 for...of 搭配数组,但 for...in 依然有其用途)。如果不加判断,for...in 会枚举所有可枚举的自身属性以及原型链上的可枚举属性。这可能会导致你处理了本不该处理的属性。

const baseConfig = {  timeout: 5000,  logLevel: 'info'};const userConfig = Object.create(baseConfig);userConfig.maxRetries = 3; // 用户自定义的属性for (const key in userConfig) {  // 如果不加 hasOwn 判断,这里会输出 timeout 和 logLevel  // 而我们可能只关心 userConfig 自身设定的属性  console.log(`Key: ${key}, Value: ${userConfig[key]}`);}// 实际输出:// Key: maxRetries, Value: 3// Key: timeout, Value: 5000// Key: logLevel, Value: info

在这种情况下,如果你只想获取 userConfig 对象“自己”定义的属性,那么 in 操作符就显得力不从心了。你不得不额外加上 Object.hasOwn(或 hasOwnProperty)来过滤,就像这样:

for (const key in userConfig) {  if (Object.hasOwn(userConfig, key)) {    console.log(`Own Key: ${key}, Value: ${userConfig[key]}`);  }}// 实际输出:// Own Key: maxRetries, Value: 3

这不仅增加了代码的复杂性,也反映出 in 操作符在判断“自有属性”这个意图上的不足。它更适合判断“属性是否存在于对象或其原型链上”,这和“属性是否属于对象本身”是两个不同的概念。理解这种差异,对于编写健壮和意图明确的代码至关重要。

使用 Object.hasOwn 相比 hasOwnProperty 有哪些优势?

说到 Object.hasOwn,很多人自然会想到它和 Object.prototype.hasOwnProperty 的关系。毕竟,它们的功能看起来几乎一样:都只检查对象自身的属性,不涉及原型链。那么,为什么还要引入 Object.hasOwn 呢?主要原因在于安全性和简洁性。

Object.prototype.hasOwnProperty 是一个方法,它存在于 Object.prototype 上。这意味着,任何对象都可以通过原型链继承并调用它。但问题是,如果一个对象本身就有一个名为 hasOwnProperty 的属性(或者说,它“覆盖”了原型链上的 hasOwnProperty 方法),那么直接调用 object.hasOwnProperty(propertyName) 就会出问题。

看这个例子:

const maliciousObject = {  data: 'some data',  hasOwnProperty: 'I am a string, not a function!' // 恶意或意外覆盖};// 尝试检查 data 属性try {  console.log(maliciousObject.hasOwnProperty('data'));} catch (e) {  console.error('Oops, hasOwnProperty is not a function!', e);  // TypeError: maliciousObject.hasOwnProperty is not a function}// 这种写法是为了避免上述问题,但显得冗长console.log(Object.prototype.hasOwnProperty.call(maliciousObject, 'data')); // true

在上面的例子中,maliciousObject 意外地(或者说,故意地)将 hasOwnProperty 属性设置成了一个字符串,而不是一个函数。当你尝试调用 maliciousObject.hasOwnProperty('data') 时,JavaScript 会尝试执行一个字符串,结果自然是报错。为了规避这种风险,我们不得不使用 Object.prototype.hasOwnProperty.call(maliciousObject, 'data') 这种更安全但更繁琐的写法。

Object.hasOwn 的出现,彻底解决了这个问题。它是一个静态方法,直接挂载在 Object 构造函数上,而不是通过原型链继承。这意味着你不需要担心 hasOwnProperty 方法被覆盖的问题,因为它根本就不依赖于对象自身的 hasOwnProperty 属性。

const maliciousObject = {  data: 'some data',  hasOwnProperty: 'I am a string, not a function!'};console.log(Object.hasOwn(maliciousObject, 'data')); // true (安全且简洁)console.log(Object.hasOwn(maliciousObject, 'hasOwnProperty')); // true (它自身确实有这个属性)

不仅如此,Object.hasOwn 的命名也更直观,更符合现代JavaScript的API设计风格。它直接表达了“对象是否拥有自己的属性”这个意图,让代码的阅读者能够一眼看出其目的。在日常开发中,能用更简洁、更安全的方式表达相同的逻辑,何乐而不为呢?

什么时候你可能仍然需要使用 in 操作符?

尽管 Object.hasOwn 在检查自有属性方面表现出色,并且在大多数场景下都是更优的选择,但我们也不能一概而论地完全抛弃 in 操作符。in 操作符有其特定的应用场景,尤其当你确实需要检查一个属性是否存在于对象或其原型链上的任何位置时,它依然是最佳选择。

举个例子,如果你在编写一个库或者框架,需要检查一个对象是否实现了某个接口(即是否包含某个方法),而这个方法可能是在原型链上定义的,那么 in 操作符就显得非常合适。

class Logger {  log(message) {    console.log(`[LOG]: ${message}`);  }}class ErrorHandler extends Logger {  error(message) {    console.error(`[ERROR]: ${message}`);  }}const myErrorHandler = new ErrorHandler();// 我想知道 myErrorHandler 是否具备 log 方法,它可能继承自 Loggerconsole.log('log' in myErrorHandler); // true (log方法在原型链上)console.log(Object.hasOwn(myErrorHandler, 'log')); // false (log方法不在 myErrorHandler 自身)// 我想知道 myErrorHandler 是否具备 error 方法console.log('error' in myErrorHandler); // true (error方法在 myErrorHandler 自身)console.log(Object.hasOwn(myErrorHandler, 'error')); // true

在这个例子中,如果你想确认 myErrorHandler 实例能否执行 log 操作,那么 in 操作符就能准确地告诉你,即使 log 方法是继承而来的。而 Object.hasOwn 则会告诉你 log 不是它“自己”的属性,这在某些情况下可能不是你想要的答案。

另一个常见场景是与 for...in 循环结合使用,如果你确实希望遍历所有可枚举的(包括继承的)属性,那么 in 操作符自然是其核心构成部分。当然,在大多数现代JavaScript开发中,我们更倾向于使用 Object.keys()Object.values()Object.entries() 来处理自有属性,或者使用 for...of 循环处理数组或可迭代对象

所以,关键在于你的意图:

如果你想知道一个属性是否直接存在于对象本身,请使用 Object.hasOwn。如果你想知道一个属性是否存在于对象或其原型链上的任何位置,那么 in 操作符就是你的工具

理解这两种操作符的设计哲学和适用场景,能够帮助你写出更精确、更符合预期的JavaScript代码。它们不是非此即彼的替代品,而是各有侧重、互为补充的存在。

以上就是JavaScript如何用Object.hasOwn替代in操作符的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1511978.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
事件循环中的“调用栈”和“任务队列”如何交互?
上一篇 2025年12月20日 06:54:29
浏览器中的requestIdleCallback和事件循环有什么关系?
下一篇 2025年12月20日 06:54:42

相关推荐

  • UC浏览器自带的截图功能快捷键是什么 UC浏览器内置截图快捷键使用说明

    首先通过快捷键或图标触发截图,再选择区域完成截取。UC浏览器支持三种方式:1. 使用Ctrl+Shift+X(Windows)或Command+Shift+X(Mac)快捷键截图;2. 点击地址栏右侧剪刀图标进行全屏、可见区域或自定义截图;3. 在设置中启用手势控制,使用三指下滑手势快速截图。所有截…

    2026年9月21日
    000
  • 怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧

    怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧怎样在iPhone情侣模式中设置情侣专属表情?个性化聊天的技巧

    通过Memoji、第三方贴纸应用和iOS 16+抠图功能,可为情侣打造专属表情包;结合自定义聊天背景、语音消息、共享相册等方式,既能提升聊天趣味性,又能保持沟通效率,增强情感连接。 在iPhone上设置情侣专属表情,与其说是开启一个内置的“情侣模式”,不如说是巧妙利用iOS系统和第三方应用提供的各种…

    2026年9月21日 用户投稿
    100
  • 如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程

    如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程如何用SumoPaint的AI裁剪图片?快速完成智能图片裁剪教程

    答案:SumoPaint虽无AI裁剪功能,但可通过魔棒、套索工具精确选区,结合图层蒙版与羽化、反选等操作实现智能裁剪效果,最后按需导出PNG或JPG高质量文件。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 在SumoPaint中,虽然它不…

    2026年9月21日 用户投稿
    000
  • Java OOP如何使用内部类提高代码组织性

    内部类提升Java代码组织性与封装性,成员内部类增强封装,静态内部类分离逻辑,局部与匿名内部类简化回调,私有内部类隐藏实现细节。 内部类在Java面向对象编程中是一种有效提升代码组织性和封装性的工具。通过将一个类定义在另一个类的内部,可以更好地表达类之间的逻辑关系,控制访问权限,并减少命名冲突。合理…

    2026年9月21日
    000
  • MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    mysql的缓存机制主要包括innodb缓冲池、查询缓存和操作系统文件系统缓存等,其中innodb缓冲池是性能优化的核心。1. innodb缓冲池缓存表数据和索引页,减少磁盘i/o,提升读写效率;2. 查询缓存因失效频繁及锁竞争问题,在高并发场景下易成瓶颈,已在mysql 8.0中移除;3. 操作系…

    2026年9月21日 用户投稿
    100
  • VSCode中竖线怎么设置_VSCode编辑区竖线(标尺)显示与配置教程

    在VSCode中启用垂直标尺需修改settings.json文件中的editor.rulers属性,如设置{ “editor.rulers”: [80, 120] }可在第80和120列显示竖线,提升代码对齐与可读性;虽原生不支持自定义颜色样式,但可通过安装Guides或In…

    2026年9月21日
    100
  • Linux之包管理工具(RPM和YUM)

    包管理工具1. rpm包1.1 rpm指令1.1.1 查询指令使用rpm查询已安装的rpm列表:rpm -qa | grep xx 检查是否已安装firefox:rpm -qa | grep firefox 如果显示i686或i386,表示32位系统,noarch表示通用rpm -qa:列出所有已安…

    2026年9月21日
    000
  • windows11磁盘分区怎么操作_windows11磁盘分区调整方法

    可通过系统磁盘管理或易我分区大师调整Windows 11分区。先使用磁盘管理压缩卷释放未分配空间,再新建简单卷;或用易我分区大师无损调整分区,拖动滑块释放空间后合并至目标分区,最后执行任务完成操作。 如果您希望对Windows 11的硬盘进行重新规划,但不确定如何安全地拆分或合并存储空间,则可能是由…

    2026年9月21日
    100
  • Java集合框架在数据处理中的应用实例

    使用Set去重:通过LinkedHashSet去除标签重复并保持顺序;2. Map统计频次:利用HashMap统计单词出现次数;3. List结合Comparator排序:按年龄升序、姓名降序排列用户;4. 集合嵌套处理数据:用Map组织部门与员工列表。集合框架提升数据处理效率与代码可读性。 Jav…

    2026年9月21日
    000
  • 如何为iPhone12Pro刷机固件下载?一步步教你操作

    首先使用爱思助手一键下载适用于iPhone 12 Pro的iOS 18固件,若失败则手动导入IPSW文件,最后可通过恢复模式配合电脑工具强制刷机完成系统重装。 如果您尝试为您的设备重新安装操作系统,但无法获取正确的系统文件,则可能是由于固件下载路径不正确或工具不支持。以下是解决此问题的步骤: 本文运…

    2026年9月21日
    000
  • 如何使用XGBoost训练AI大模型?优化机器学习模型的步骤

    XGBoost并非用于训练GPT类大模型,而是擅长处理结构化数据的高效梯度提升算法,其优势在于速度快、准确性高、支持并行计算、内置正则化与缺失值处理,适用于表格数据建模;通过分阶段超参数调优(如学习率、树深度、采样策略)、结合贝叶斯优化与交叉验证,并配合特征工程、数据预处理和集成学习等关键步骤,可显…

    2026年9月21日
    000
  • VSCode远程开发:配置容器与SSH连接的最佳实践解析

    使用VSCode远程开发提升效率,通过Remote-Containers和Remote-SSH实现环境标准化。1. 配置.devcontainer文件夹,用devcontainer.json定义容器环境,推荐自定义Dockerfile并预装工具;2. SSH连接需配置公钥认证、~/.ssh/conf…

    2026年9月21日
    100
  • Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]

    Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]

    大家好,很高兴再次与你们见面,我是你们的朋友全栈君。 Ubuntu安装前言最近我决定将开发环境切换到Linux系统,经过一番研究,我选择了Ubuntu桌面版,因为它不仅美观,而且作为生产系统的生态环境也非常好。于是,我开始寻找安装Ubuntu双系统的方法。安装方法有三种: 虚拟机安装:这种方法无法充…

    2026年9月21日 用户投稿
    000
  • 如何在Java中配置与数据库连接环境

    答案:Java中配置数据库连接需引入JDBC驱动,如MySQL在Maven中添加对应依赖;通过DriverManager或连接池(如HikariCP)获取Connection,使用try-with-resources管理资源;建议将连接参数存入properties文件,并处理常见问题如驱动加载、权限…

    2026年9月21日
    000
  • 蝴蝶号无人直播课程推荐:学习路径+核心技能梳理

    蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理

    蝴蝶号无人直播的核心在于内容打磨与技术跑通。首要任务是明确直播间定位,如卖货、涨粉或娱乐,并据此准备高清视频、背景音乐及互动文案等素材。其次是技术实现,使用obs等推流工具配合虚拟摄像头软件,但需注意平台参数要求与网络稳定性,以确保直播流畅。最后是运营优化,通过短视频预热、自动回复、数据复盘等方式提…

    2026年9月21日 用户投稿
    000
  • TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤

    TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤

    TuxPaint没有AI裁剪工具,只能通过橡皮擦或填充工具手动模拟裁剪效果,适合儿童创意绘画但不适合精确图像编辑。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ TuxPaint作为一个面向儿童的绘画软件,其实并没有专门的“AI工具”来执行…

    2026年9月21日 用户投稿
    100
  • win11管理员权限不够怎么办_win11管理员权限不足解决方法

    首先以管理员身份运行程序,其次修改文件权限或启用Administrator账户,最后通过调整UAC设置或注册表禁用UAC来解决权限不足问题。 如果您在使用Windows 11时尝试执行某些系统级操作,但提示权限不足或被拒绝,即使当前账户为管理员,也可能是由于用户账户控制(UAC)或特定文件/程序的权…

    2026年9月21日
    100
  • Java Executors类提供哪些线程池方法

    Executors类提供创建线程池的静态方法:newFixedThreadPool创建固定大小线程池,适用于稳定负载;newCachedThreadPool创建可缓存线程池,适合短期异步任务;newSingleThreadExecutor创建单线程池,保证任务顺序执行;newScheduledThr…

    2026年9月21日
    200
  • Windows&Linux双系统安装流程

    Windows&Linux双系统安装流程Windows&Linux双系统安装流程Windows&Linux双系统安装流程Windows&Linux双系统安装流程

    大家好,很高兴再次见到大家,我是你们的朋友全栈君。 注意事项:在安装Windows与Linux双系统时,建议先安装Windows系统,否则可能会导致grub引导被覆盖的问题。 Windows 10系统安装 制作启动盘(优启通链接)https://www.php.cn/link/219b87ff108…

    2026年9月21日 用户投稿
    200
  • VSCode中怎么使用REM_VSCode移动端REM布局编写与换算教程

    答案:REM_VSCode插件可自动将像素转换为REM,需配置rootFontSize和precision,支持自动与手动转换,确保与html的font-size一致,配合media query适配不同屏幕,若插件异常可检查配置、重启或重装,替代工具有postcss-pxtorem、在线转换工具及浏…

    2026年9月21日
    100

发表回复

登录后才能评论
关注微信