首页 web前端 js教程 [每次突破] JavaScript 如何判断属性是否存在

[每次突破] JavaScript 如何判断属性是否存在

Jan 09, 2025 pm 08:30 PM

[每次突破] JavaScript 如何判断属性是否存在

前言

在 JavaScript 开发中,我们常常需要判断在于一个对象中一个属性是否存在。
由于 JavaScript 是一个比较松散的语言,导致我们很难去做一些比较严格的事。就比如这个问题,“属性是否存在”在 JavaScript 里的定义出现了偏差,到底什么时候是存在,什么是算不存在。这没有对错之分,只是在不同的语境下,不同的开发需求下,“存在”的含义是不一样的。
这里我就说一说比较常用的5种判断方式,和它们存在的问题。

方法 1:布尔(Boolean)判定

这里举个例子:

const obj1 = { name: 'Andy', age: 21 }
const obj2 = { name: 'Alice' }

console.log( obj1.age ? '存在' : '不存在' ); // 存在
console.log( obj2.age ? '存在' : '不存在' ); // 不存在

先说说这种方式的缺陷吧
如果:

const obj = { name: 'Baby', age: 0 }

console.log( obj.age ? '存在' : '不存在' ); // 不存在

这种情况下,age应是 “存在”,但是会被判断成“不存在”。

那么这种方式是不是就不能用呢?
这就要根据业务的开发需求了。
如果你知道在你的业务开发需求里,这个属性是不可能为0,空字符串啊,NaN啊,undefined之类的,那么这个判定还是可行的。
如果你放在更加严格的环境,那么这个方式就有缺陷的。

方法 2: 可选链 (?.) 和 undefined 检查

还是先举例:

const obj1 = { name: 'Andy', age: 21 }
const obj2 = { name: 'Alice' }

console.log( obj1?.age !== undefined ? '存在' : '不存在' ); // 存在
console.log( obj2?.age !== undefined ? '存在' : '不存在' ); // 不存在

这个对比的逻辑就是,在JS语言里,一个不存在的值就是undefined。

但是在一个对象里,也可能出现的这种情况:

const obj = {
    name: 'Andy',
    age: undefined
}

像这种情况,那么age这个属性应该是“存在”呢,还是“不存在”?

这也就不好说了,还是要看你的具体的需求环境。

方法 3: 查找Object.keys()

如果说,我就要知道一个对象里有没有一个属性age,我不管它的值是什么。

我们就可以用这个方式:

const obj = { name: 'Andy', age: 21 }

console.log( Object.keys(obj).includes('age') ? '存在' : '不存在' ); // 存在

使用Object.keys()可以得到自身的可枚举属性名来进行判断。

这里有两个关键词,一个是“自身的”(own),一个是“可枚举”(enumerable)。

首先说,什么是“自身的”

比方说这里有一个对象,给对象加一个属性name:

const obj = { name: 'Andy' }
// `name` 就是 obj 自身的属性
console.log( Object.keys(obj) ); // [ 'name' ]

那么什么不是自身的属性呢?这里就要扯到“原型”了。一个对象是有原型,在原型上加的属性就不是“自身的”属性了。

const obj = Object.create( { type: 'human' } );
obj.name = 'Andy';

console.log( obj.name ); // Andy
console.log( obj.type ); // human
console.log( Object.keys(obj) ); // [ 'name' ]

这个例子,你怎么判断type是不是obj的属性呢?这就不好说了对吧,你可以说是,也可以说不是。这就是语言宽松环境带来的问题。

但你需要知道的是,在这种情况下,Object.keys()是拿不到原型上的属性。因为它只能读取“自身的”属性。

第二个是,“可枚举”

这里就要提到属性描述符了,我很多同事都不知道,在JS语言里,在一个对象里,每个属性都有一个描述符的。
怎么读取呢?我们打印看吧:

const obj1 = { name: 'Andy', age: 21 }
const obj2 = { name: 'Alice' }

console.log( obj1.age ? '存在' : '不存在' ); // 存在
console.log( obj2.age ? '存在' : '不存在' ); // 不存在

你会发现,这个描述符其实也是一个对象,它描述了这个属性的一些信息,比如说值(value),可重写(writable),还有这个(enumerable)可枚举 ...

这个enumerable定义了那个属性,是否可以被枚举,比如for...in循环时候可以读取这个属性,Object.keys()也是如此。

如果我重新定义一个属性为不可枚举的,那么Object.keys()就读取不到这个属性了。

const obj = { name: 'Baby', age: 0 }

console.log( obj.age ? '存在' : '不存在' ); // 不存在

这里就涉及到了属性描述符的相关知识了,这个是原生JS语言非常重要的知识,而我发现很多我认识的前端程序员都缺乏这种原生JS的知识。

那么如果说你要判断的属性要求只要是自身的属性,不管可不可枚举呢?那么就不能用Object.keys()了。可以用接下来的方法。

方法 4:使用 Object.hasOwn() 或 hasOwnProperty()

Object.hasOwn() 和 hasOwnProperty() 有什么区别呢?

Object.hasOwn() 是 ES2022 加入的方法,用于检查对象是否自身具有某个属性,用于替代 hasOwnProperty 的促优处理。由于这是后来加入的方法,兼容性还是个问题,如果只考虑新版本的浏览器还是可以用的。

这两个方法判断的是 “自身的” 属性名,所以不管是不是可枚举,都能被读取。

const obj1 = { name: 'Andy', age: 21 }
const obj2 = { name: 'Alice' }

console.log( obj1?.age !== undefined ? '存在' : '不存在' ); // 存在
console.log( obj2?.age !== undefined ? '存在' : '不存在' ); // 不存在

为什么要用Object.hasOwn(),由于对象的hasOwnProperty()有可能被修改:

const obj = {
    name: 'Andy',
    age: undefined
}

如果你要判断的属性名,不要求是自身的和可枚举,原型也行,那么就要用最后一个方法了。

方法 5: in 运算符

in 运算符用于判断一个属性是否存在于对象或其原型链中。

const obj = { name: 'Andy', age: 21 }

console.log( Object.keys(obj).includes('age') ? '存在' : '不存在' ); // 存在

总结

这些方法种,没有说那个方法是正确的,那个错误的。并不是每个场景都适合同一种方法,根据情况遵守最佳实践,以增强代码可读性和安全性。

以上是[每次突破] JavaScript 如何判断属性是否存在的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

为什么要将标签放在的底部? 为什么要将标签放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

如何在JS中与日期和时间合作? 如何在JS中与日期和时间合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和时间处理需注意以下几点:1.创建Date对象有多种方式,推荐使用ISO格式字符串以保证兼容性;2.获取和设置时间信息可用get和set方法,注意月份从0开始;3.手动格式化日期需拼接字符串,也可使用第三方库;4.处理时区问题建议使用支持时区的库,如Luxon。掌握这些要点能有效避免常见错误。

什么是在DOM中冒泡和捕获的事件? 什么是在DOM中冒泡和捕获的事件? Jul 02, 2025 am 01:19 AM

事件捕获和冒泡是DOM中事件传播的两个阶段,捕获是从顶层向下到目标元素,冒泡是从目标元素向上传播到顶层。1.事件捕获通过addEventListener的useCapture参数设为true实现;2.事件冒泡是默认行为,useCapture设为false或省略;3.可使用event.stopPropagation()阻止事件传播;4.冒泡支持事件委托,提高动态内容处理效率;5.捕获可用于提前拦截事件,如日志记录或错误处理。了解这两个阶段有助于精确控制JavaScript响应用户操作的时机和方式。

垃圾收集如何在JavaScript中起作用? 垃圾收集如何在JavaScript中起作用? Jul 04, 2025 am 12:42 AM

JavaScript的垃圾回收机制通过标记-清除算法自动管理内存,以减少内存泄漏风险。引擎从根对象出发遍历并标记活跃对象,未被标记的则被视为垃圾并被清除。例如,当对象不再被引用(如将变量设为null),它将在下一轮回收中被释放。常见的内存泄漏原因包括:①未清除的定时器或事件监听器;②闭包中对外部变量的引用;③全局变量持续持有大量数据。V8引擎通过分代回收、增量标记、并行/并发回收等策略优化回收效率,降低主线程阻塞时间。开发时应避免不必要的全局引用、及时解除对象关联,以提升性能与稳定性。

JavaScript模块上的确定JS综述:ES模块与COMPORJS JavaScript模块上的确定JS综述:ES模块与COMPORJS Jul 02, 2025 am 01:28 AM

ES模块和CommonJS的主要区别在于加载方式和使用场景。1.CommonJS是同步加载,适用于Node.js服务器端环境;2.ES模块是异步加载,适用于浏览器等网络环境;3.语法上,ES模块使用import/export,且必须位于顶层作用域,而CommonJS使用require/module.exports,可在运行时动态调用;4.CommonJS广泛用于旧版Node.js及依赖它的库如Express,ES模块则适用于现代前端框架和Node.jsv14 ;5.虽然可混合使用,但容易引发问题

如何在node.js中提出HTTP请求? 如何在node.js中提出HTTP请求? Jul 13, 2025 am 02:18 AM

在Node.js中发起HTTP请求有三种常用方式:使用内置模块、axios和node-fetch。1.使用内置的http/https模块无需依赖,适合基础场景,但需手动处理数据拼接和错误监听,例如用https.get()获取数据或通过.write()发送POST请求;2.axios是基于Promise的第三方库,语法简洁且功能强大,支持async/await、自动JSON转换、拦截器等,推荐用于简化异步请求操作;3.node-fetch提供类似浏览器fetch的风格,基于Promise且语法简单

var vs Let vs const:快速JS综述解释器 var vs Let vs const:快速JS综述解释器 Jul 02, 2025 am 01:18 AM

var、let和const的区别在于作用域、提升和重复声明。1.var是函数作用域,存在变量提升,允许重复声明;2.let是块级作用域,存在暂时性死区,不允许重复声明;3.const也是块级作用域,必须立即赋值,不可重新赋值,但可修改引用类型的内部值。优先使用const,需改变变量时用let,避免使用var。

为什么DOM操纵缓慢,如何优化? 为什么DOM操纵缓慢,如何优化? Jul 01, 2025 am 01:28 AM

操作DOM变慢的主要原因在于重排重绘成本高和访问效率低。优化方法包括:1.减少访问次数,缓存读取值;2.批量处理读写操作;3.合并修改,使用文档片段或隐藏元素;4.避免布局抖动,集中处理读写;5.使用框架或requestAnimationFrame异步更新。

See all articles