JS里怎么判断一个对象是否为空?怎么分清它到底是啥类型?

对象{},它明明看着是空的,但JS说它"不是假值",if ({})还是成立的。这就尴尬了。

到底怎么才算"空对象"?又怎么知道一个东西到底是对象、数组、还是别的啥?

一、怎么判断一个对象是否为空?

先说结论:一个"空对象"通常是指它没有任何可枚举的自有属性

比如:

js 复制代码
const obj1 = {};
const obj2 = { name: '张三' };

obj1是空的,obj2不是。

方法1:Object.keys()

这是我现在最常用的方法。

js 复制代码
function isEmpty(obj) {
  return Object.keys(obj).length === 0;
}

isEmpty({}); // true
isEmpty({ name: '张三' }); // false

使用场景:我之前做后台管理系统,有个接口返回用户配置:

js 复制代码
const config = await fetchConfig();
if (isEmpty(config)) {
  alert('请先设置你的偏好');
}

这个方法简单直接,而且只看对象自己的属性,不看原型链,很安全。

注意:它只适用于普通对象。比如数组、函数这些,也可以用Object.keys()。但数组更自然的判断是arr.length === 0

方法2:for...in遍历

老派但可靠的方法:

js 复制代码
function isEmpty(obj) {
  for (let key in obj) {
    return false; // 只要能进循环,说明有属性
  }
  return true;
}

这个方法也行,但要小心原型链上的属性。比如:

js 复制代码
const obj = {};
obj.__proto__.abc = 'xxx'; // 别这么干,只是举例

这时候for...in会遍历到abc,但Object.keys()不会。

所以如果你不确定对象有没有被"污染"原型,建议配合 hasOwnProperty

js 复制代码
function isEmpty(obj) {
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      return false;
    }
  }
  return true;
}

不过现在大家一般不乱改原型了,所以 Object.keys 更省心。

方法3:JSON.stringify()

有人这么写:

js 复制代码
JSON.stringify(obj) === '{}'

这方法能用,但有坑:

  • 如果对象里有undefined、函数、Symbol,会被忽略,结果可能不准。
  • 性能差一点,毕竟要序列化。

所以我不推荐,除非你特别确定数据结构。

二、怎么区分数据类型?

JS的类型判断一直是个"玄学"。比如:

js 复制代码
typeof []      // "object"
typeof null    // "object"

这就很离谱。所以我们得用别的办法。

1. 判断是不是数组

别再用typeof了,用Array.isArray()

js 复制代码
Array.isArray([])     // true
Array.isArray({})     // false

使用场景:我之前写一个数据处理函数,接收的参数可能是单个对象,也可能是对象数组:

js 复制代码
function handleData(data) {
  const list = Array.isArray(data) ? data : [data];
  list.forEach(item => console.log(item));
}

handleData({name: '张三'});        // 包装成数组
handleData([{name: '张三'}]);      // 直接用

这样写,调用方就不用每次都包数组了,很灵活。

2. 判断是不是 null 或 undefined

这个简单:

js 复制代码
if (value == null) { // 等价于 value === null || value === undefined
  // 处理空值
}

== null比分开写两个条件更简洁,而且语义清晰。


3. 判断是不是普通对象(不是数组、不是 null、不是函数等)

有时候我们需要区分"纯对象"和别的类型。

可以用这个小技巧:

js 复制代码
function isPlainObject(obj) {
  return obj?.constructor === Object;
}

解释一下:

  • obj?. 是可选链,防止 obj 是 null/undefined
  • constructor 属性指向构造函数
  • 普通对象的构造函数就是 Object

测试一下:

js 复制代码
isPlainObject({})           // true
isPlainObject([])           // false,数组的 constructor 是 Array
isPlainObject(null)         // false
isPlainObject(function(){}) // false,函数的 constructor 是 Function

这个方法在处理 API 返回数据时特别有用。比如:

js 复制代码
// 假设接口可能返回对象或数组
const res = await api.getData();
if (isPlainObject(res)) {
  showUserInfo(res);
} else if (Array.isArray(res)) {
  showList(res);
}

小结

  • 判断空对象 :优先用 Object.keys(obj).length === 0
  • 判断数组 :用 Array.isArray()
  • 判断 null/undefined :用 value == null
  • 判断是不是普通对象 :用 obj?.constructor === Object

JS的类型系统确实有点乱,但我们没必要追求完美的判断方式。只要在你的业务场景下能正确工作,就是好方法

相关推荐
__zRainy__3 分钟前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.40 分钟前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~2 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华2 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子5 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅5 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni5 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学6 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
赵庆明老师7 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim