这个问题的答案是社区的努力。编辑现有答案以改进这篇文章。它目前不接受新的答案或交互。
在 AJAX 请求之后,有时我的应用程序可能会返回一个空对象,例如:
var a = {};
我如何检查是否是这种情况?
// because Object.keys(new Date()).length === 0;
// we have to do some additional check
obj // 👈 null and undefined check
&& Object.keys(obj).length === 0
&& Object.getPrototypeOf(obj) === Object.prototype
但请注意,这会创建一个不必要的数组(keys
的返回值)。
前 ECMA 5:
function isEmpty(obj) {
for(var prop in obj) {
if(Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
}
return JSON.stringify(obj) === JSON.stringify({});
}
jQuery.isEmptyObject({}); // true
_.isEmpty({}); // true
_.isEmpty({}); // true
Hoek.deepEqual({}, {}); // true
Ext.Object.isEmpty({}); // true
angular.equals({}, {}); // true
R.isEmpty({}); // true
如果 ECMAScript 5 support 可用,您可以使用 Object.keys()
:
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
对于 ES3 和更早版本,没有简单的方法可以做到这一点。您必须明确地遍历属性:
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
isEmpty()
,因此如果它有属性,它应该返回 false
function isEmpty(object) { for(var i in object) { return true; } return false; }
必须在 11 年后更正。这是更正:function isEmpty(obj) { return !(() => { for (const i in obj) { return true; } return false; })(); }
function isObjectEmpty(obj) { for (const i in obj) return false; return true; }
对于那些有同样问题但使用 jQuery 的人,您可以使用 jQuery.isEmptyObject。
表现
2020.01.17 今天,我在 Chrome v79.0、Safari v13.0.4 和 Firefox v72.0 上对 macOS High Sierra 10.13.6 进行了测试;对于选择的解决方案。
结论
基于 for-in (A, J, L, M) 的解决方案是最快的
基于 JSON.stringify(B,K) 的解决方案很慢
令人惊讶的是,基于Object(N)的解决方案也很慢
注意:此表与下面的照片不匹配。
https://i.stack.imgur.com/yqmYR.png
细节
下面的代码段中提供了 15 个解决方案。如果您想在您的机器上运行性能测试,请单击 HERE。此链接于 2021.07.08 更新,但最初执行了测试 here - 上表中的结果来自那里(但现在看起来该服务不再有效)。
var log = (s, f) => console.log(`${s} --> {}:${f({})} {k:2}:${f({ k: 2 })} `);函数 A(obj) { for (var i in obj) return false;返回真; } 函数 B(obj) { 返回 JSON.stringify(obj) === "{}"; } 函数 C(obj) { return Object.keys(obj).length === 0; } function D(obj) { return Object.entries(obj).length === 0; } 函数 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" || !Boolean(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; } } 返回真; } function K(obj) { for (var prop in obj) { if (obj.hasOwnProperty(prop)) { return false; } } 返回 JSON.stringify(obj) === JSON.stringify({}); } function L(obj) { for (var prop in obj) { if (obj.hasOwnProperty(prop)) return false; } 返回真; } function M(obj) { for (var k in obj) { if (obj.hasOwnProperty(k)) { return false; } } 返回真; } 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 !==空 && 键 !== 未定义; })()); } 日志(“A”,A);日志(“B”,B);日志(“C”,C);日志(“D”,D);日志(“E”,E);日志(“F”,F);日志(“G”,G);日志(“H”,H);日志(“我”,我);日志(“J”,J);日志(“K”,K);日志(“L”,L);日志(“M”,M);日志(“N”,N);日志(“O”,O);
https://i.stack.imgur.com/ma99z.png
(o => { for(let k in o) return false; return true; })(obj)
您可以使用 Underscore.js。
_.isEmpty({}); // true
_.isEmpty
:npm i lodash.isempty
if(Object.getOwnPropertyNames(obj).length === 0){
//is empty
}
见http://bencollier.net/2011/04/javascript-is-an-object-empty/
Object.getOwnPropertyNames(new Date()).length === 0
;所以这个答案可能会产生误导。
使用 JSON.stringify 怎么样?它几乎在所有现代浏览器中都可用。
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
JSON.stringify(new Error('gotcha')) === '{}'
是 true
老问题,但只是有问题。如果您的唯一目的是检查对象是否为空,那么包含 JQuery 并不是一个好主意。相反,只要深入 JQuery's code,您就会得到答案:
function isEmptyObject(obj) {
var name;
for (name in obj) {
if (obj.hasOwnProperty(name)) {
return false;
}
}
return true;
}
如果您使用的是较新的浏览器,则有一种简单的方法。 Object.keys(obj).length === 0
keys
属性从何而来?
Object.keys
是一种标准方法,但对象没有 keys 属性。因此,此代码会将任何对象报告为空,除非它偶然碰巧有一个名为 key
的属性,其值又是一个名为 length
的属性,它不为零。可怕!
Object.keys(new Date()).length === 0
;所以这个答案可能会产生误导。
对于空对象,使用 Object.keys(obj).length (如上面对 ECMA 5+ 的建议)要慢 10 倍!保持老派(for...in)选项。
在 Node、Chrome、Firefox 和 IE 9 下测试,很明显对于大多数用例:
(for...in...) 是最快的选择!
Object.keys(obj).length 比空对象慢 10 倍
JSON.stringify(obj).length 总是最慢的(并不奇怪)
Object.getOwnPropertyNames(obj).length 比 Object.keys(obj).length 花费的时间更长,在某些系统上可能更长。
底线性能明智,使用:
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;
}
在 Is object empty? 查看详细的测试结果和测试代码
Object.keys
速度较慢,但代码较少。在一个小页面上,这被称为......也许是 10 次......考虑到额外代码的额外解析时间,这仍然会更慢吗?
我正在使用这个。
function isObjectEmpty(object) {
var isEmpty = true;
for (keys in object) {
isEmpty = false;
break; // exiting since we found that the object is not empty
}
return isEmpty;
}
例如:
var myObject = {}; // Object is empty
var isEmpty = isObjectEmpty(myObject); // will return true;
// populating the object
myObject = {"name":"John Smith","Address":"Kochi, Kerala"};
// check if the object is empty
isEmpty = isObjectEmpty(myObject); // will return false;
更新
或者
你可以使用 isEmptyObject 的 jQuery 实现
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
}
我的看法:
函数 isEmpty(obj) { return Object.keys(obj).length === 0; } var a = { a: 1, b: 2 } var b = {} console.log(isEmpty(a)); // false console.log(isEmpty(b)); // 真的
只是,我认为目前并非所有浏览器都实现 Object.keys()
。
Object.keys(new Date()).length === 0
;所以这个答案可能会产生误导。
只是一种解决方法。如果没有数据,您的服务器可以生成一些特殊属性吗?例如:var a = {empty:true};然后您可以轻松地在您的 AJAX 回调代码中检查它。另一种检查方法: if (a.toSource() === "({})") // then 'a' 为空
编辑:如果您使用任何 JSON 库(fe JSON.js),那么您可以尝试 JSON.encode() 函数并针对空值字符串测试结果。
toSource()
是非标准的,在 IE 或 Opera(以及可能我未检查的其他浏览器)中不起作用
toSource
属性;根据 MDC,它是在 JS1.3(即 Netscape Navigator 4.06)中引入的,但它不在 ECMA-262 第 3 版中!
toSource()
也是一种可怕的方法(如 JSON.encode()
)。它需要构建一个代表整个对象的字符串来检查它是否为空。将事物转换为字符串会产生开销,但此外,如果您的对象具有一百万个属性,则需要转换一百万个事物,而实际上只看一个就会让您知道它不是空的。
function isEmpty(obj) {
for(var i in obj) { return false; }
return true;
}
Object
时,这也是正确的,因为它是可枚举的,并且 for in
语句循环遍历可枚举的属性。
下面的例子展示了如何测试一个 JavaScript 对象是否为空,如果是空的,我们的意思是它没有自己的属性。
该脚本适用于 ES6。
const isEmpty = (obj) => { if (obj === null || obj === undefined || Array.isArray(obj) || typeof obj !== 'object' ) { return true; } 返回 Object.getOwnPropertyNames(obj).length === 0; };控制台.clear(); console.log('-----'); console.log(isEmpty('')); // true console.log(isEmpty(33)); // true console.log(isEmpty([])); // true console.log(isEmpty({})); // true console.log(isEmpty({ length: 0, custom_property: [] })); // false console.log('-----'); console.log(isEmpty('Hello')); // true console.log(isEmpty([1, 2, 3])); // true console.log(isEmpty({ test: 1 })); // false console.log(isEmpty({ length: 3, custom_property: [1, 2, 3] })); // false console.log('-----'); console.log(isEmpty(new Date())); // true console.log(isEmpty(Infinity)); // true console.log(isEmpty(null)); // true console.log(isEmpty(undefined)); // 真的
对于这种情况,jQuery 有特殊的功能 isEmptyObject()
:
jQuery.isEmptyObject({}) // true
jQuery.isEmptyObject({ foo: "bar" }) // false
在 http://api.jquery.com/jQuery.isEmptyObject/ 上阅读更多信息
正确答案是:
function isEmptyObject(obj) {
return (
Object.getPrototypeOf(obj) === Object.prototype &&
Object.getOwnPropertyNames(obj).length === 0 &&
Object.getOwnPropertySymbols(obj).length === 0
);
}
这将检查:
对象的原型正是 Object.prototype。
该对象没有自己的属性(无论可枚举性如何)。
该对象没有自己的属性符号。
换句话说,该对象与使用 {}
创建的对象没有区别。
警告!当心 JSON 的限制。
javascript:
obj={ f:function(){} };
alert( "Beware!! obj is NOT empty!\n\nobj = { f:function(){} }" +
"\n\nJSON.stringify( obj )\n\nreturns\n\n" +
JSON.stringify( obj ) );
显示
Beware!! obj is NOT empty! obj = { f:function(){} } JSON.stringify( obj ) returns {}
除了 Thevs 的回答:
var o = {};
alert($.toJSON(o)=='{}'); // true
var o = {a:1};
alert($.toJSON(o)=='{}'); // false
这是 jquery + jquery.json
$.isEmptyObject()
,请不要将周期浪费在不明显的转换上。
1. 使用 Object.keys
Object.keys 将返回一个数组,其中包含对象的属性名称。如果数组的长度为0,那么我们就知道对象是空的。
function isEmpty(obj) {
return Object.keys(obj).length === 0 && empty.constructor === Object;
}
我们还可以使用 Object.values 和 Object.entries 进行检查。这通常是确定对象是否为空的最简单方法。
2. 使用 for...in 循环对象属性
for...in 语句将遍历对象的可枚举属性。
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
在上面的代码中,我们会循环遍历对象的属性,如果一个对象至少有一个属性,那么它将进入循环并返回 false。如果对象没有任何属性,那么它将返回 true。
#3。使用 JSON.stringify 如果我们对对象进行字符串化并且结果只是一个左括号和右括号,我们就知道该对象是空的。
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
4. 使用 jQuery
jQuery.isEmptyObject(obj);
5. 使用下划线和 Lodash
_.isEmpty(obj);
纯原版 Javascript,完全向后兼容
函数 isObjectDefined (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 true } } return JSON.stringify(Obj) !== JSON.stringify({}) } } console.log(isObjectDefined()) // false console.log(isObjectDefined('')) // false console.log(isObjectDefined(1)) // false console.log(isObjectDefined('string')) // false console.log(isObjectDefined(NaN) ) // false console.log(isObjectDefined(null)) // false console.log(isObjectDefined({})) // false console.log(isObjectDefined([])) // false console.log(isObjectDefined({a : ''})) // 真的
要真正接受 ONLY {}
,使用 Lodash 在 Javascript 中执行此操作的最佳方法是:
_.isEmpty(value) && _.isPlainObject(value)
IsEmpty Object,出乎意料地失去了它的意义,即:它是编程语义,当我们著名的雅虎大师向 ECMA 介绍定制的不可枚举的对象属性时,它们被接受了。
[如果你不喜欢历史 - 可以直接跳到工作代码]
我看到很多很好的答案\这个问题\问题的解决方案。但是,获取 ECMA 脚本的最新扩展并不是正确的方法。我们过去常常阻止 Web 以保持 Netscape 4.x 和基于 Netscape 的页面工作和项目的活力,这(顺便说一下)是极其原始的落后和特殊的,拒绝使用新的 W3C 标准和主张 [在那个时候是相当具有革命性的并且对编码人员友好],而现在对我们自己的遗产却是残酷的。
杀死 Internet Explorer 11 是完全错误的!是的,一些自“冷战”时代以来一直处于休眠状态的渗透微软的老战士同意了——出于所有错误的原因。 - 但这并不正确!
在您的答案中使用新引入的方法\属性并将其作为发现(“它一直存在,但我们没有注意到它”)而不是新发明(实际上是什么)移交,是有点“绿色”和有害。大约 20 年前,我曾经犯过这样的错误,当时我仍然无法分辨那里已经存在什么,并将所有我能找到参考的东西都视为一种常见的工作解决方案......
向后兼容性很重要!
我们只是还不知道。这就是我需要分享我的“百年老”通用解决方案的原因,该解决方案仍然向后和向前兼容,以适应不可预见的未来。
对 in 运算符有很多攻击,但我认为这样做的人终于明白了,并真正开始理解和欣赏真正的动态类型语言,如 JavaScript 及其美丽的本质。
我的方法旨在简单而有核,出于上述原因,我不称其为“空”,因为该词的含义不再准确。 Is Enumerable,似乎是具有确切含义的词。
function isEnum( x ) { for( var p in x )return!0; return!1 };
一些用例:
isEnum({1:0})
true
isEnum({})
false
isEnum(null)
false
谢谢阅读!
我能找到的最佳单线解决方案(更新):
isEmpty = obj => !Object.values(obj).filter(e => typeof e !== 'undefined').length; console.log(isEmpty({})) // true console.log(isEmpty({a: undefined, b: undefined})) // true console.log(isEmpty({a: undefined, b: void 1024, c : void 0})) // true console.log(isEmpty({a: [undefined, undefined]})) // false console.log(isEmpty({a: 1})) // false console.log(isEmpty ({a: ''})) // false console.log(isEmpty({a: null, b: undefined})) // false
Object.keys().length
已在 2009 年针对此问题提出过建议。stackoverflow.com/a/679937/2943403 所以这个发布的答案一半有缺陷,另一半是多余的。
另一种选择是使用 is.js (14kB) 而不是 jquery (32kB)、lodash (50kB) 或 underscore (16.4kB)。 is.js 被证明是上述可用于确定对象是否为空的库中最快的库。
http://jsperf.com/check-empty-object-using-libraries
显然,所有这些库并不完全相同,因此如果您需要轻松操作 DOM,那么 jquery 可能仍然是一个不错的选择,或者如果您需要的不仅仅是类型检查,那么 lodash 或 underscore 可能会很好。至于 is.js,语法如下:
var a = {};
is.empty(a); // true
is.empty({"hello": "world"}) // false
与下划线和 lodash 的 _.isObject()
一样,这不仅适用于 objects
,还适用于 arrays
和 strings
。
这个库在底层使用了与 Object.keys
类似的 Object.getOwnPropertyNames
,但 Object.getOwnPropertyNames
更彻底,因为它将返回如 here 所述的可枚举和不可枚举的属性。
is.empty = function(value) {
if(is.object(value)){
var num = Object.getOwnPropertyNames(value).length;
if(num === 0 || (num === 1 && is.array(value)) || (num === 2 && is.arguments(value))){
return true;
}
return false;
} else {
return value === '';
}
};
如果您不想引入库(这是可以理解的)并且您知道您只检查对象(而不是数组或字符串),那么以下函数应该适合您的需要。
function isEmptyObject( obj ) {
return Object.getOwnPropertyNames(obj).length === 0;
}
这只是比 is.js 快一点,只是因为你没有检查它是否是一个对象。
我知道这不能 100% 回答您的问题,但我之前也遇到过类似的问题,以下是我用来解决这些问题的方法:
我有一个可能返回空对象的 API。因为我知道 API 需要哪些字段,所以我只检查是否存在任何必填字段。
例如:
API 返回 {} or {agentID: '1234' (required), address: '1234 lane' (opt),...}
。在我的调用函数中,我只会检查
if(response.data && response.data.agentID) {
do something with my agentID
} else {
is empty response
}
这样我就不需要使用那些昂贵的方法来检查对象是否为空。如果我的调用函数没有 agentID 字段,该对象将为空。
我们也可以使用 vanilla js 来处理 null 或 undefined 检查,如下所示,
函数 isEmptyObject(obj) { return !!obj && Object.keys(obj).length === 0 && obj.constructor === Object; } //测试 isEmptyObject(new Boolean()); // false isEmptyObject(new Array()); // false isEmptyObject(new RegExp()); // false isEmptyObject(new String()); // false isEmptyObject(new Number()); // false isEmptyObject(new Function()); // false isEmptyObject(new Date()); // false isEmptyObject(null); // false isEmptyObject(undefined); // false isEmptyObject({}); // 真的
我喜欢我想出的这个,这里有一些其他答案的帮助。以为我会分享它。
Object.defineProperty(Object.prototype, 'isEmpty', { get() { for(var p in this) { if (this.hasOwnProperty(p)) {return false} } return true; } });让用户 = {};让颜色 = {primary: 'red'};让尺寸= {sm:100,md:200,lg:300}; console.log( '\nusers =', users, '\nusers.isEmpty ==> ' + users.isEmpty, '\n\n-------------\n', '\ ncolors =', 颜色, '\ncolors.isEmpty ==>' + colors.isEmpty, '\n\n-------------\n', '\nsizes =', 尺寸, '\nsizes.isEmpty ==> ' + sizes.isEmpty, '\n', '' );
奇怪的是,我还没有遇到一个解决方案来比较对象的值而不是任何条目的存在(也许我在许多给定的解决方案中错过了它)。如果对象的所有值都未定义,我想介绍一个对象被认为是空的情况:
const isObjectEmpty = obj => Object.values(obj).every(val => typeof val === "undefined") console.log(isObjectEmpty({})) // true console.log(isObjectEmpty({ foo: undefined , bar: undefined })) // true console.log(isObjectEmpty({ foo: false, bar: null })) // false
示例用法
假设,为了举例,您有一个函数 (paintOnCanvas
),它从其参数(x
、y
和 size
)中销毁值。如果 all 都未定义,则它们将被排除在结果选项集之外。如果不是,它们不是,它们都包括在内。
function paintOnCanvas ({ brush, x, y, size }) {
const baseOptions = { brush }
const areaOptions = { x, y, size }
const options = isObjectEmpty(areaOptions) ? baseOptions : { ...baseOptions, areaOptions }
// ...
}
Object.keys(new Date()).length === 0
;所以这个答案可能会产生误导。ECMA5+
代码中检查obj.contructor===Object
?我们只能使用此代码obj // 👈 null and undefined check && Object.keys(obj).length === 0