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

相关推荐
Dontla1 天前
Tailwind CSS介绍(现代CSS框架,与传统CSS框架Bootstrap对比)Tailwind介绍
前端·css·bootstrap
yinuo1 天前
uniapp微信小程序安卓手机Touchend事件无法触发
前端
你的人类朋友1 天前
【Node】Node.js 多进程与多线程:Cluster 与 Worker Threads 入门
前端·后端·node.js
闲人编程1 天前
使用Celery处理Python Web应用中的异步任务
开发语言·前端·python·web·异步·celery
excel1 天前
前端读取文件夹并通过 SSH 上传:完整实现方案 ✅
前端
谢尔登1 天前
【Nest】日志记录
javascript·中间件·node.js
双向331 天前
【征文计划】基于Rokid CXR-M SDK 打造AI 实时会议助手:从连接到自定义界面的完整实践
前端
Lei活在当下1 天前
【业务场景架构实战】6. 从业务痛点到通用能力:Android 优先级分页加载器设计
前端·后端·架构
你的人类朋友1 天前
什么是基础设施中间件
前端·后端
知识分享小能手1 天前
微信小程序入门学习教程,从入门到精通,WXML(WeiXin Markup Language)语法基础(8)
前端·学习·react.js·微信小程序·小程序·vue·个人开发