检查对象是否为空的最快方法是什么?
有没有比这更快更好的方法:
function count_obj(obj){
var i = 0;
for(var key in obj){
++i;
}
return i;
}
检查对象是否为空的最快方法是什么?
有没有比这更快更好的方法:
function count_obj(obj){
var i = 0;
for(var key in obj){
++i;
}
return i;
}
对于 ECMAScript5(并非所有浏览器都支持),您可以使用:
Object.keys(obj).length === 0
我假设空的意思是“没有自己的属性”。
// 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
仍然会给你正确的结果。
编辑:请注意,您可能应该使用ES5 解决方案而不是这个,因为如今 ES5 支持很普遍。不过它仍然适用于 jQuery。
简单和跨浏览器的方式是使用jQuery.isEmptyObject
:
if ($.isEmptyObject(obj))
{
// do something
}
更多:http : //api.jquery.com/jQuery.isEmptyObject/
不过你需要jquery。
让我们把这个婴儿放在床上;在 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;
}
节点下的结果:
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
测试具有 1 个键的对象 0.000346 0.000458 0.000577 0.000657
测试具有 2 个键的对象 0.000375 0.00046 0.000565 0.000773
测试具有 3 个键的对象 0.000406 0.000476 0.000577 0.000904
测试具有 4 个键的对象 0.000435 0.000487 0.000589 0.001031
测试具有 5 个键的对象 0.000465 0.000501 0.000604 0.001148
测试具有 6 个键的对象 0.000492 0.000511 0.000618 0.001269
测试具有 7 个键的对象 0.000528 0.000527 0.000637 0.00138
测试具有 8 个键的对象 0.000565 0.000538 0.000647 0.00159
测试具有 100 个键的对象 0.003718 0.00243 0.002535 0.01381
测试具有 1000 个键的对象 0.0337 0.0193 0.0194 0.1337
请注意,如果您的典型用例测试具有少量键的非空对象,并且您很少测试空对象或具有 10 个或更多键的对象,请考虑使用 Object.keys(obj).length 选项。- 否则采用更通用的 (for... in...) 实现。
请注意,Firefox 似乎对 Object.keys(obj).length 和 Object.getOwnPropertyNames(obj).length 提供了更快的支持,使其成为任何非空对象的更好选择,但是当涉及到空对象时,( for...in...) 速度快了 10 倍。
我的 2 美分是 Object.keys(obj).length 是一个糟糕的主意,因为它创建了一个键对象只是为了计算里面有多少键,而不是销毁它!为了创建该对象,他需要循环公开键...那么为什么要使用它而不是 (for... in...) 选项:)
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);