对象是空的吗?

检查对象是否为空的最快方法是什么?

有没有比这更快更好的方法:

function count_obj(obj){
var i = 0;
for(var key in obj){
++i;
}


return i;
}
746638 次浏览
function isEmpty( o ) {
for ( var p in o ) {
if ( o.hasOwnProperty( p ) ) { return false; }
}
return true;
}

我假设的意思是“没有自己的属性”。

// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;


function isEmpty(obj) {


// null and undefined are "empty"
if (obj == null) return true;


// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0)    return false;
if (obj.length === 0)  return true;


// If it isn't an object at this point
// it is empty, but it can't be anything *but* empty
// Is it empty?  Depends on your application.
if (typeof obj !== "object") return true;


// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}


return true;
}

例子:

isEmpty(""), // true
isEmpty(33), // true (arguably could be a TypeError)
isEmpty([]), // true
isEmpty({}), // true
isEmpty({length: 0, custom_property: []}), // true


isEmpty("Hello"), // false
isEmpty([1,2,3]), // false
isEmpty({test: 1}), // false
isEmpty({length: 3, custom_property: [1,2,3]}) // false

如果你只需要处理ECMAScript5浏览器,你可以使用Object.getOwnPropertyNames代替hasOwnProperty循环:

if (Object.getOwnPropertyNames(obj).length > 0) return false;

这将确保即使对象只有不可枚举的属性,isEmpty仍然会给你正确的结果。

对于ECMAScript5(不是所有浏览器都支持),你可以使用:

Object.keys(obj).length === 0

这可能有点俗气。你可以试试这个。

if (JSON.stringify(data).length === 2) {
// Do something
}

不确定是否有此方法的缺点

下划线lodash都有一个方便的isEmpty()函数,如果你不介意添加一个额外的库的话。

_.isEmpty({});

编辑:注意,你可能应该使用ES5的解决方案来代替这个,因为现在ES5支持广泛的。但它仍然适用于jQuery。


简单且跨浏览器的方法是使用jQuery.isEmptyObject:

if ($.isEmptyObject(obj))
{
// do something
}

更多:http://api.jquery.com/jQuery.isEmptyObject/

但是你需要jquery。

不需要图书馆。

function(){ //must be within a function
var obj = {}; //the object to test


for(var isNotEmpty in obj) //will loop through once if there is a property of some sort, then
return alert('not empty')//what ever you are trying to do once


return alert('empty'); //nope obj was empty do this instead;
}
if (Object.getOwnPropertyNames(obj1).length > 0)
{
alert('obj1 is empty!');
}

快速联机'dictionary'-objects:

function isEmptyDict(d){for (var k in d) return false; return true}

你可以写一个回退数组。isArray和Object。getOwnPropertyNames不可用

XX.isEmpty = function(a){
if(Array.isArray(a)){
return (a.length==0);
}
if(!a){
return true;
}
if(a instanceof Object){


if(a instanceof Date){
return false;
}


if(Object.getOwnPropertyNames(a).length == 0){
return true;
}
}
return false;
}

很惊讶在这么一个基本的JS问题上看到这么多弱的答案…上面的答案也不好,原因如下:

  1. 它生成一个全局变量
  2. undefined上返回true
  3. 使用for...in,它本身非常慢
  4. for...in中的函数是无用的-返回没有hasOwnProperty魔力的false将正常工作

事实上,有一个更简单的解决方案:

function isEmpty(value) {
return Boolean(value && typeof value === 'object') && !Object.keys(value).length;
}

优雅的方式——使用钥匙

var myEmptyObj = {};
var myFullObj = {"key":"value"};
console.log(Object.keys(myEmptyObj).length); //0
console.log(Object.keys(myFullObj).length); //1

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys < a href = " https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys " > < / >

https://lodash.com/docs#isEmpty非常方便:

_.isEmpty({})   // true
_.isEmpty()     // true
_.isEmpty(null) // true
_.isEmpty("")   // true

情况有多糟?

function(obj){
for(var key in obj){
return false; // not empty
}


return true; // empty
}

也许你可以用这个决定:

var isEmpty = function(obj) {
for (var key in obj)
if(obj.hasOwnProperty(key))
return false;
return true;
}

这是我的解决方案

function isEmpty(value) {
if(Object.prototype.toString.call(value) === '[object Array]') {
return value.length == 0;
} else if(value != null && typeof value === 'object') {
return Object.getOwnPropertyNames(value).length  == 0;
} else {
return !(value || (value === 0));
}
}

解围球

这里有一个好方法

function isEmpty(obj) {
if (Array.isArray(obj)) {
return obj.length === 0;
} else if (typeof obj === 'object') {
for (var i in obj) {
return false;
}
return true;
} else {
return !obj;
}
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isArray(a) {
return Object.prototype.toString.call(a) === '[object Array]'
}
function isObject(a) {
return Object.prototype.toString.call(a) === '[object Object]'
}
function isEmpty(a) {
if (null == a || "" == a)return!0;
if ("number" == typeof a || "string" == typeof a)return!1;
var b = !0;
if (isArray(a)) {
if (!a.length)return!0;
for (var c = 0; c < a.length; c++)isEmpty(a[c]) || (b = !1);
return b
}
if (isObject(a)) {
for (var d in a)hasOwnProperty.call(a, d) && (isEmpty(a[d]) || (b = !1));
return b
}
return!0
}

让我们把这个孩子放在床上;在Node, Chrome, Firefox和ie9下测试,很明显,对于大多数用例:

  • (for…in…)是最快的选择!
  • 种(obj)。对于空对象,长度要慢10倍
  • JSON.stringify (obj)。长度总是最慢的(不足为奇)
  • 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;
}

Node下的结果:

  • 第一个结果:return (Object.keys(obj).length === 0)
  • 第二个结果:for (var x in obj) { return false; }...
  • 第三个结果:for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }...
  • 第四结果:return ('{}' === JSON.stringify(obj))

测试0键的对象 0.00018 0.000015 0.000015 0.000324 < / p >

测试带有1个键的对象 0.000346 0.000458 0.000577 0.000657 < / p >

测试带有2个键的对象 0.000375 0.00046 0.000565 0.000773 < / p >

测试有3个键的对象 0.000406 0.000476 0.000577 0.000904 < / p >

测试带有4个键的对象 0.000435 0.000487 0.000589 0.001031 < / p >

测试5个键的对象 0.000465 0.000501 0.000604 0.001148 < / p >

测试有6个键的对象 0.000492 0.000511 0.000618 0.001269 < / p >

测试对象的7个键 0.000528 0.000527 0.000637 0.00138 < / p >

测试8个键的对象 0.000565 0.000538 0.000647 0.00159 < / p >

测试对象100个键 0.003718 0.00243 0.002535 0.01381 < / p > 测试带有1000个键的对象 0.0337 0.0193 0.0194 0.1337 < / p >

请注意,如果您的典型用例测试一个具有很少键的非空对象,并且很少测试空对象或具有10个或更多键的对象,请考虑object .keys(obj)。长度的选择。-否则就用更通用的(for…)在…)的实现。

注意,Firefox似乎对Object.keys(obj)有更快的支持。length和Object.getOwnPropertyNames(obj)。长度,使它成为任何非空对象的更好选择,但当涉及到空对象时,(for…in…)只是快10倍。

我认为Object.keys(obj)。长度是一个糟糕的想法,因为它创建一个键的对象只是为了计算里面有多少个键,而不是破坏它!为了创建该对象,他需要循环显式键…那么为什么用it而不用the (for…)在…)选项:)

var a = {};


function timeit(func,count) {
if (!count) count = 100000;
var start = Date.now();
for (i=0;i<count;i++) func();
var end = Date.now();
var duration = end - start;
console.log(duration/count)
}


function isEmpty1() {
return (Object.keys(a).length === 0)
}
function isEmpty2() {
for (x in a) { return false; }
return true;
}
function isEmpty3() {
for (x in a) { if (a.hasOwnProperty(x))  return false; }
return true;
}
function isEmpty4() {
return ('{}' === JSON.stringify(a))
}




for (var j=0;j<10;j++) {
a = {}
for (var i=0;i<j;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4);
}


a = {}
for (var i=0;i<100;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4, 10000);


a = {}
for (var i=0;i<1000;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1,10000);
timeit(isEmpty2,10000);
timeit(isEmpty3,10000);
timeit(isEmpty4,10000);

我修改了肖恩·维埃拉的代码来满足我的需要。Null和undefined根本不算作对象,数字、布尔值和空字符串返回false。

'use strict';


// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;


var isObjectEmpty = function(obj) {
// null and undefined are not empty
if (obj == null) return false;
if(obj === false) return false;
if(obj === true) return false;
if(obj === "") return false;


if(typeof obj === "number") {
return false;
}
    

// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0)    return false;
if (obj.length === 0)  return true;


// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
    

    

    

return true;
};


exports.isObjectEmpty = isObjectEmpty;

假设你有以下对象:

var obj1= {};
var obj2= {test: "test"};

不要忘记我们不能使用===符号来测试对象是否相等,因为他们得到继承,所以如果你使用ECMA 5和更高版本的javascript,答案很简单,你可以使用下面的函数:

function isEmpty(obj) {
//check if it's an Obj first
var isObj = obj !== null
&& typeof obj === 'object'
&& Object.prototype.toString.call(obj) === '[object Object]';


if (isObj) {
for (var o in obj) {
if (obj.hasOwnProperty(o)) {
return false;
break;
}
}
return true;
} else {
console.error("isEmpty function only accept an Object");
}
}

结果如下:

isEmpty(obj1); //this returns true
isEmpty(obj2); //this returns false
isEmpty([]); // log in console: isEmpty function only accept an Object
funtion isEmpty(o,i)
{
for(i in o)
{
return!1
}
return!0
}
var x= {}
var y= {x:'hi'}
console.log(Object.keys(x).length===0)
console.log(Object.keys(y).length===0)


true
false

http://jsfiddle.net/j7ona6hz/1/