有时在进行 AJAX 请求后,我的应用程序可能会返回一个空对象,例如:
var a = {};
我该如何检查是否是这种情况?
有时在进行 AJAX 请求后,我的应用程序可能会返回一个空对象,例如:
var a = {};
我该如何检查是否是这种情况?
您可以使用 for…in 循环和 Object.hasOwn
(ECMA 2022+) 测试来检查对象是否具有任何自有属性:
function isEmpty(obj) {
for (const prop in obj) {
if (Object.hasOwn(obj, prop)) {
return false;
}
}
return true;
}
如果您还需要区分类似{}
的空对象和其他没有自己属性的对象(例如Date
),则可以进行各种(不幸的是需要特定类型)的类型检查:
function isEmptyObject(value) {
if (value == null) {
// null or undefined
return false;
}
if (typeof value !== 'object') {
// boolean, number, string, function, etc.
return false;
}
const proto = Object.getPrototypeOf(value);
// consider `Object.create(null)`, commonly used as a safe map
// before `Map` support, an empty object as well as `{}`
if (proto !== null && proto !== Object.prototype) {
return false;
}
return isEmpty(value);
}
Object.prototype
进行比较将无法识别跨域对象。
不要使用Object.keys(obj).length
。它的复杂度为O(N),因为它创建一个仅包含所有属性名称的数组,只是为了获取该数组的长度。遍历对象可以实现相同的目标,但其复杂度为O(1)。var
替换const
,用Object.prototype.hasOwnProperty.call
替换Object.hasOwn
:function isEmpty(obj) {
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
}
return true
}
jQuery.isEmptyObject({}); // true
_.isEmpty({}); // true
下划线:
_.isEmpty({}); // true
Hoek:
Hoek.deepEqual({}, {}); // true
Ext.Object.isEmpty({}); // true
angular.equals({}, {}); // true
R.isEmpty({}); // true
Object.keys()
:function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
isEmpty()
,所以如果它有一个属性,它应该返回 false
。 - Christophfunction isObjectEmpty(obj) { for (const key in obj) { if (obj.hasOwnProperty(key)) { return false; } } return true; }
- Michael BuenObject.hasOwn(obj, prop)
。 - colinta如果您遇到同样的问题并使用jQuery,可以使用jQuery.isEmptyObject。
今天2023年3月20日,我在MacOS Monterey 12.1(M1, 16GB)上使用Chrome v109、Safari v15.2和Firefox v110对选择的解决方案进行测试。
for-in
(A,L)的解决方案在所有浏览器上都很快或最快JSON.stringify
(B)的解决方案在所有浏览器上都最慢以下代码段中提供了解决方案。如果您想在您的计算机上运行性能测试,请单击
此答案的旧版本包含来自2020年的测试 - 此处。
答案链接: A, B, C, D, E, F, G, H, I, J, K, L, M, N, O P Q
var log = (s, f) => console.log(`${s} --> {}:${f({})} {k:2}:${f({ k: 2 })}`);
function A(obj) {
for (var i in obj) return false;
return true;
}
function B(obj) {
return JSON.stringify(obj) === "{}";
}
function C(obj) {
return Object.keys(obj).length === 0;
}
function D(obj) {
return Object.entries(obj).length === 0;
}
function E(obj) {
return Object.getOwnPropertyNames(obj).length === 0;
}
function F(obj) {
return Object.keys(obj).length === 0 && obj.constructor === Object;
}
function G(obj) {
return typeof obj === "undefined" || !Object.keys(obj)[0];
}
function H(obj) {
return Object.entries(obj).length === 0 && obj.constructor === Object;
}
function I(obj) {
return Object.values(obj).every((val) => typeof val === "undefined");
}
function J(obj) {
for (const key in obj) {
if (hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
function K(obj) {
var isEmpty = true;
for (keys in obj) {
isEmpty = false;
break;
}
return isEmpty;
}
function L(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) return false;
}
return true;
}
function M(obj) {
if (obj === null || typeof obj !== 'object' ||
Object.prototype.toString.call(obj) === '[object Array]') {
return false
} else {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
return false
}
}
return JSON.stringify(obj) === JSON.stringify({})
}
}
function N(obj) {
return (
Object.getOwnPropertyNames(obj).length === 0 &&
Object.getOwnPropertySymbols(obj).length === 0 &&
Object.getPrototypeOf(obj) === Object.prototype
);
}
function O(obj) {
return !(Object.getOwnPropertyNames !== undefined
? Object.getOwnPropertyNames(obj).length !== 0
: (function () {
for (var key in obj) break;
return key !== null && key !== undefined;
})());
}
function P(obj) {
return $.isEmptyObject(obj)
}
function Q(obj) {
return _.isEmpty(obj);
}
log("A", A);
log("B", B);
log("C", C);
log("D", D);
log("E", E);
log("F", F);
log("G", G);
log("H", H);
log("I", I);
log("J", J);
log("K", K);
log("L", L);
log("M", M);
log("N", N);
log("O", O);
log("P", P);
log("Q", Q);
<script
src="https://code.jquery.com/jquery-3.6.4.min.js"
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js" integrity="sha512-2V49R8ndaagCOnwmj8QnbT1Gz/rie17UouD9Re5WxbzRVUGoftCu5IuqqtAM9+UC3fwfHCSJR1hkzNQh/2wdtg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
obj = {a:1,b:2,c:3}
,结果显示 for(var i in obj)
仍然是最快的。https://jsperf.com/object-empty-ch/2 - Madacol(o => { for(let k in o) return false; return true; })(obj)
- Valenreturn true
,但其中一个比另一个慢25%……这表明差异是如此微小,以至于它们不应该有任何影响,它们将被包装在必然的函数调用中,在JIT和垃圾收集抖动以及其他噪声中将被淹没。 - user3840170_.isEmpty({}); // true
_.isEmpty
:npm i lodash.isempty
。 - Nick Bullif(Object.getOwnPropertyNames(obj).length === 0){
//is empty
}
参见http://bencollier.net/2011/04/javascript-is-an-object-empty/
使用JSON.stringify怎么样?现代浏览器几乎都支持它。
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
JSON.stringify(new Error('gotcha')) === '{}'
为 true
。 - onestep.ua如果你使用较新的浏览器,有一种简单的方法。
Object.keys(obj).length === 0
Object.keys
是一个标准方法,但对象没有一个名为keys的属性。因此,这段代码将报告任何对象为空,除非它偶然地具有一个名为key
的属性,并且该属性的值再次具有一个名为length
的属性,其值不为零。太可怕了! - scravyObject.keys(new Date()).length === 0
;因此这个答案可能会误导。 - cjbarth虽然这是一个旧问题,但我最近也遇到了同样的问题。如果你只是想检查对象是否为空,那么包含JQuery并不是一个好主意。相反,深入了解JQuery的代码,你就会得到答案。
function isEmptyObject(obj) {
var name;
for (name in obj) {
if (obj.hasOwnProperty(name)) {
return false;
}
}
return true;
}
isEmptyObject({ hasOwnProperty: "where is your god now?" })
- user3840170使用Object.keys(obj).length(如上所建议的ECMA 5+)对于空对象来说要慢10倍!继续使用老式方式(for...in)。
在Node、Chrome、Firefox和IE 9下进行测试,很明显在大多数情况下:
总之,在性能方面,应该使用:
function isEmpty(obj) {
for (var x in obj) { return false; }
return true;
}
或者function isEmpty(obj) {
for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }
return true;
}
请查看对象是否为空?的详细测试结果和测试代码。
Object.keys
操作较慢,但代码量较少。在一个小页面上,如果调用次数不超过 10 次,那么考虑到额外的解析时间,这是否仍会更慢? - yankee
Object.keys(new Date()).length === 0
的意思是“新建一个 Date 对象后,获取它的属性名组成的数组,并计算该数组的长度是否为 0”,但这种写法可能会产生歧义。 - cjbarth