JavaScript---如何完美的判断返回对象是否有值

如何判断一个对象为空是我们在开发中经常会遇到的问题,今天我们来聊聊几种经常使用的方法,以及在不同的场景下我们如何去使用。

1. JSON.stringify

JSON.stringify 方法可以使对象序列化,转为相应的 JSON 格式。

js
复制代码
const obj = {};

console.log(JSON.stringify(obj) === '{}')  // true

缺点:如果存在 undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。更多[1]

如下示例:

const obj = {
  a: undefined,
  b: function() {},
  c: Symbol()
}

console.log(JSON.stringify(obj) === '{}')  // true

2. for in 配合 hasOwnProperty

使用 for in 对当前对象进行遍历:

const obj = {}
Object.prototype.a = 1

function isEmptyObj(obj) {
  let flag = true
  for (let o in obj) {
    flag = false
    break
  }
  return flag
}

console.log(isEmptyObj(obj))  // false

由于 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

缺点:for in 不能遍历不可枚举的属性。

3. Object.keys

Object.keys 会返回对象自身可枚举属性组成的数组,而不会遍历原型上的属性。

const obj = {}
Object.prototype.a = 1

console.log(Object.keys(obj).length === 0)  // true

缺点:Object.keysfor in 都只能遍历可枚举属性,不能遍历不可枚举的属性。

我们使用 Object.defineProperty 将属性 enumerable 设置为 false 来进行测试,示例如下:

const obj = {}
Object.defineProperty(obj, 'a', {
  value: 1,
  enumerable: false
})

console.log(obj.a)  // 1
console.log(isEmptyObj(obj))  // true
console.log(Object.keys(obj).length === 0)  // true

4. Object.getOwnPropertyNames

使用 Object.getOwnPropertyNames 可以得到对象自身的所有属性名组成的数组(包括不可枚举属性)。

const obj = {}
Object.defineProperty(obj, 'a', {
  value: 1,
  enumerable: false
})

console.log(Object.getOwnPropertyNames(obj))  // [ 'a' ]

缺点:不能获取 Symbol 值作为名称的属性,以上的 JSON.stringifyfor in 以及 Object.keys 方法也不能获取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(isEmptyObj(obj))  // true
console.log(Object.keys(obj).length === 0)  // true

5. 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

经过测试,上面这种方法的确可以解决,但是比较繁琐,那有没有更好的方法呢?答案是有的。

6. Reflect.ownKeys

Reflect.ownKeys 方法返回一个由目标对象自身的属性组成的数组,它的返回值等同于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)),示例如下:

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

总结

判断一个对象是否为空时,使用 Reflect.ownKeys 方法最为完美。

相关推荐
xing25164 分钟前
pytest-html
前端·html·pytest
茂茂在长安14 分钟前
Linux 命令大全完整版(11)
java·linux·运维·服务器·前端·centos
Violet51515 分钟前
ECMAScript规范解读——this的判定
javascript
知识分享小能手1 小时前
Html5学习教程,从入门到精通,HTML5 简介语法知识点及案例代码(1)
开发语言·前端·javascript·学习·前端框架·html·html5
IT、木易1 小时前
大白话React第二章深入理解阶段
前端·javascript·react.js
晚安7201 小时前
Ajax相关
前端·javascript·ajax
图书馆钉子户1 小时前
怎么使用ajax实现局部刷新
前端·ajax·okhttp
bin91531 小时前
DeepSeek 助力 Vue 开发:打造丝滑的单选按钮(Radio Button)
前端·javascript·vue.js·ecmascript·deepseek
qianmoQ1 小时前
第五章:工程化实践 - 第五节 - Tailwind CSS 常见问题解决方案
前端·css
那就可爱多一点点1 小时前
超高清大图渲染性能优化实战:从页面卡死到流畅加载
前端·javascript·性能优化