js如何判断一个对象是空对象

判断对象是否为空的问题不仅在面试中经常被问到,在项目开发中也会经常使用到--比如我们在判断后端数据是否为空时所做的相应处理,以避免项目运行时产生问题。下面就说几种判断对象是否为空的方法。

有以下六种方式判断对象是否为空:

  • 使用JSON.striginfy()

  • 使用Object.keys()

  • for...in循环

  • Object.getOwnPropertyNames()

  • Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols

  • Reflect.ownKeys

JSON.striginfy() 

这是最常用的一个判断方法,该方法可以序列化对象并将其转换为相应的JSON字符串格式。

let obj = {};
console.log(JSON.stringify(obj) === "{}");//返回true

⚠️注意:

如果存在未定义属性值,或函数,Symbol值,在序列化过程中,它们将被忽略或转换为空。

const obj = {
  a: undefined,
  b: function() {},
  c: Symbol()
}
console.log(JSON.stringify(obj) === '{}')  // true

所以不是很推荐这种方式,但如果能够确认不会出现以上这种情况的话,这种方法当然是最简单的一种方式。

Object.keys() 

这也是会经常用到的方式。Object.keys()返回对象的属性名组成的一个数组,若长度为0 ,则为空对象。

let obj = {}
console.log(Object.keys(obj).length == 0);//返回true

⚠️注意:

只能遍历可枚举的属性,但不能遍历非枚举的属性

例如,我们先给obj定义一个属性a,将其设置成可枚举类型,结果当然是false:

const obj = {}
Object.defineProperty(obj, 'a', {
  value: 1,
  enumerable: true
})
console.log(obj.a) // 1
console.log(Object.keys(obj).length === 0) // false

接下来我们再将enumerable 设置成false,属性a将不会统计出来,结果显示obj为空对象:

const obj = {}
Object.defineProperty(obj, 'a', {
  value: 1,
  enumerable: false
})
console.log(obj.a) // 1
console.log(Object.keys(obj).length === 0) // true

for in循环 

for in循环需要和hasOwnProperty结合使用来判断对象是否为空。因为在for in循环时也会遍历原型上的属性,为了排除原型上的属性,所以使用hasOwnProperty。


const obj = {}
Object.prototype.a = 1 // 原型上的值

function isEmptyObj(obj) {
  let flag = true
  for (let o in obj) {
    if (obj.hasOwnProperty(o)) {
      flag = false
      break
    }
  }
  return flag
}
console.log(isEmptyObj(obj))  // true

⚠️注意:

这个方法同Object.keys一样,不能遍历非枚举的属性演示如上...

Object.getOwnPropertyNames() 

以上两种方法都不能获取非枚举属性,那有没有办法获取到非枚举属性呢?噔噔噔...就是这个Object.getOwnPropertyNames()!Object.getOwnPropertyNames()可以获取对象本身所有属性名称(包括非枚举属性)组成的数组。

const obj = {}
Object.defineProperty(obj, 'a', {
  value: 1,
  enumerable: false
})
console.log(Object.getOwnPropertyNames(obj))  // [ 'a' ]

似乎解决了前面的难题,但另一个难题又出现了----无法获取作为名称属性的Symbol值。上代码:


const a = Symbol()
const obj = {
  [a]: 1
}

console.log(obj)  // { [Symbol()]: 1 }
console.log(Object.getOwnPropertyNames(obj).length === 0)  // true
console.log(JSON.stringify(obj) === '{}')  // true
console.log(Object.keys(obj).length === 0)  // true

好吧,是所有的方法都识别不出symbol的值。在找到完美的解决方案之前我们坚持不懈。有没有既能非枚举属性,又能识别symbol的方法嘞?答案是有滴,请看下面的方法

Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols 

Object.getOwnPropertyNames唯一已知的缺点是无法获取以Symbol为名的属性。而Object.getOwnPropertySymbols 只能获取以Symbol为名的属性。所以这两个方法是相互补充,一拍即合。

const a = Symbol()
const obj1 = {
  [a]: 1
}
const obj2 = {b: 2}
const obj3 = {}
Object.defineProperty(obj3, 'a', {
  value: 1,
  enumerable: false
})
const obj4 = {}

function getLength(obj) {

  return Object.getOwnPropertyNames(obj)
    .concat(Object.getOwnPropertySymbols(obj))
    .length
}
console.log(getLength(obj1) === 0)  // false
console.log(getLength(obj2) === 0)  // false
console.log(getLength(obj3) === 0)  // false
console.log(getLength(obj4) === 0)  // true

嗯嗯嗯,经过上面的测试,完全符合我们的预期,perfect!似乎是有点麻烦😡 我们再得寸进尺一下,有没有既能识别非枚举属性,又能识别symbol值,又很简单的方法嘞?有...继续往下看

Reflect.ownKeys

其返回值也是数组。


const a = Symbol()
const obj1 = {
  [a]: 1
}
const obj2 = {b: 2}
const obj3 = {}
Object.defineProperty(obj3, 'a', {
  value: 1,
  enumerable: false
})
const obj4 = {}

console.log(Reflect.ownKeys(obj1).length === 0)  // false
console.log(Reflect.ownKeys(obj2).length === 0)  // false
console.log(Reflect.ownKeys(obj3).length === 0)  // false
console.log(Reflect.ownKeys(obj4).length === 0)  // true

总结 

JSON.striginfy(),Object.keys(),for...in循环,Object.getOwnPropertyNames()适合简单的判断,不能识别非枚举属性,不能识别symbol值。

Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols和Reflect.ownKeys能识别非枚举属性,也能识别symbol值。

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕彬-前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值