最可靠的方法是 Object.keys(obj).length === 0,因其只检查自有可枚举属性,行为明确、兼容性好;其他方法如 JSON.stringify 或 for...in 存在忽略属性、原型污染或性能等问题。

JavaScript 中判断对象是否为空,最可靠的方法是 Object.keys(obj).length === 0。它只关心「自有可枚举属性」,行为明确、兼容性好、不易误判。
为什么不用 JSON.stringify(obj) === '{}'
这个写法看似直观,但有多个陷阱:
-
JSON.stringify()会忽略undefined、函数、Symbol 键,导致{a: undefined, b() {}}也被判为空 - 原型链上的属性不会被序列化,但你可能并不想忽略它们——不过通常你确实只关心自身属性,这点反而算“歪打正着”
- 如果对象有自定义
toJSON()方法(比如Date实例),结果完全不可控 - 性能差:要先序列化再字符串比较,比遍历键快不了,还多一层开销
for...in 循环 + hasOwnProperty 能用吗?
能用,但需谨慎。这是兼容老环境(如 IE8)时的备选方案:
function isEmpty(obj) {
if (obj == null || typeof obj !== 'object') return true;
for (let key in obj) {
if (obj.hasOwnProperty(key)) return false;
}
return true;
}
注意点:
立即学习“Java免费学习笔记(深入)”;
- 必须加
obj.hasOwnProperty(key),否则会把原型链上可枚举属性(比如给Object.prototype挂了方法)也计入 - 不能处理
null或非对象类型,得提前 guard - ES6+ 环境下不如
Object.keys()简洁安全
还有哪些“看起来像但实际不推荐”的方法?
这些写法在特定场景会出错,容易埋坑:
-
Object.entries(obj).length === 0:和Object.keys()行为基本一致,但多了一次数组构造开销,没必要 -
Reflect.ownKeys(obj).length === 0:会包含 Symbol 键和不可枚举属性,比如Object.defineProperty(obj, 'x', {value: 1, enumerable: false})会让它返回false,而多数业务场景只关心可枚举属性 -
!Object.keys(obj)[0]:靠取第一个键是否存在来判断,对空对象成立,但遇到{'0': 'a'}这种键名是字符串数字的对象,Object.keys()[0]是'0',取反为false,误判为非空
真正要注意的是:空对象判定从来不是纯技术问题,而是语义问题——你要判断的是“有没有可枚举自有属性”,还是“能不能被 JSON 安全序列化”,或是“原型链是否干净”。大多数时候,Object.keys(obj).length === 0 就是那个平衡了准确性、可读性和兼容性的答案。











