广告

JavaScript 判断空对象的5种方法全解析:适用场景、边界条件与性能对比

本文聚焦 JavaScript 判断空对象的5种方法全解析:适用场景、边界条件与性能对比。通过对比不同方法在实际场景中的表现,读者可以快速判断在某个业务场景下应优先使用哪一种方法来判断空对象,从而提升代码鲁棒性与性能表现。

1. 使用 Object.keys 判断空对象

适用场景

适用于只关注对象的可枚举自身属性是否为空的场景,因为 Object.keys(obj) 返回对象自身的可枚举属性名数组,长度为 0 时可认为对象在该定义下“空”。

JavaScript 判断空对象的5种方法全解析:适用场景、边界条件与性能对比

注意:该方法对非对象类型或 null 不成立,需要进行类型判断;此外,数组也会通过该判断,因为数组也是对象的一种。因此在判断目标限定为“普通对象”时,需额外进行类型检查。

实现与代码

function isEmptyObject_keys(obj) {if (obj === null || typeof obj !== 'object') return false;return Object.keys(obj).length === 0;
}

边界条件与性能对比

边界条件:如果对象存在不可枚举属性或符号属性,这些属性不会被 keys 计入,因此对象在某些定义下可能被误判为“空对象”;对包含不可枚举属性但无可枚举属性的对象,结果会把它当作空对象。这也是定义空对象时需要清晰约定的点

性能要点:Object.keys 通常是获取自身可枚举属性的最快路径之一,时间复杂性接近 O(n),n 为对象自身可枚举属性数量。在大量对象判断场景下,它的性能通常优于需要遍历不可枚举属性的方案。

实战要点

若你需要对“只有可枚举属性”的空对象进行快速判断,该方法是最常用的首选;但在存在隐藏属性或符号属性的对象时,需结合其他方法进行更严格的判断。

示例对比

如果一个对象包含一个不可枚举属性:Object.keys仍返回空数组,而对象并非严格意义上的“空对象”;因此请结合业务定义来选择判定策略。

性能样例

在微基准中,对比同样大小的对象,keys 往往比获取全部属性的方案更快,适合对大量对象逐个判断的场景

2. 使用 Object.getOwnPropertyNames 判断空对象

适用场景

适用于检测对象的所有自有属性(包括可枚举和不可枚举)是否存在,因为 getOwnPropertyNames 会返回对象的所有自有属性名,包含不可枚举属性。

边界条件:与 Object.keys 的结果不同点在于不可枚举属性也会被计入,因此如果对象存在不可枚举属性但没有可枚举属性,这个方法会认为对象不是空对象。

实现与代码

function isEmptyObject_getOwnPropertyNames(obj) {if (obj === null || typeof obj !== 'object') return false;return Object.getOwnPropertyNames(obj).length === 0;
}

边界条件与对比要点

对比 Object.keys,该方法更严格一些,因为不可枚举属性也会被统计;若你的业务定义要求包含不可枚举属性的存在即不为空,这是更贴近直觉的判断。

性能对比

性能通常低于 Object.keys,因为需要枚举更多类型的属性,在高频场景下需要权衡

3. 使用 Reflect.ownKeys 判断空对象

适用场景

面向最严格的自有属性检测,Reflect.ownKeys(obj) 会返回对象自身的所有属性键,包括字符串键和符号键,且包括可枚举与不可枚举的属性。

边界条件:如果对象存在 Symbol 属性,Reflect.ownKeys 会把它们统计在内,因此空判断将更严格地排除这些情况。

实现与代码

function isEmptyObject_reflect(obj) {if (obj === null || typeof obj !== 'object') return false;return Reflect.ownKeys(obj).length === 0;
}

关注点与注意事项

适用于需要排除所有自有属性的场景,包括符号属性;但在旧浏览器环境中可能需要 polyfill,以确保兼容性

性能对比

性能开销通常高于 keys/entries,因为它检索的属性集合更全面,但在需要最严格判定时可以使用

4. 使用 Object.entries 判断空对象

适用场景

面向可枚举自有属性的详细判断,Object.entries 返回一个包含所有可枚举自有属性的键值对数组,因此长度为 0 时,等价于“没有任何可枚举自有属性”。

边界条件:与 Object.keys 相似,但它直接给出键值对,便于在判断同时需要取值的场景使用;不过若对象为空或为纯空对象,返回值数组为空。对象中存在不可枚举属性或符号属性不影响结果

实现与代码

function isEmptyObject_entries(obj) {if (obj === null || typeof obj !== 'object') return false;return Object.entries(obj).length === 0;
}

边界条件与对比要点

适用于只需判断可枚举属性是否存在的场景,对于存在不可枚举或符号属性的对象,该方法会给出与实际“严格空对象”不同的结果。

性能对比

与 Object.keys 相近,在多数引擎中性能差异微小;若需要自带属性列表,entries 提供了即时的数据。

5. 使用 JSON.stringify 判断空对象

适用场景

当你需要快速判断对象在 JSON 序列化角度是否为空,即对象没有可枚举的键值对,且对象可以被安全序列化为 JSON。

边界条件:JSON.stringify 仅序列化可枚举的自有属性;如果对象存在循环引用,将抛出异常,因此需要包裹在 try/catch 结构中。

实现与代码

function isEmptyObject_json(obj) {if (obj === null || typeof obj !== 'object') return false;try {return JSON.stringify(obj) === '{}';} catch (e) {// 循环引用等序列化问题时视作非空return false;}
}

边界条件与注意事项

JSON.stringify 可能忽略不可枚举属性、Symbol 属性以及通过 toJSON 自定义序列化的结果,因此在定义“空对象”时,应明确是否以序列化结果为准。若对象存在循环引用,返回值将无法判定,需要异常处理。

性能对比

性能通常较低,因为序列化是较重的操作,在频繁判定的高并发场景中通常不推荐作为首选方法

广告