计算对象的键/财产数的最快方法是什么?是否可以在不迭代对象的情况下执行此操作?即,不做:

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) ++count;

(Firefox确实提供了一个神奇的__count__属性,但在版本4左右,这个属性被删除了。)


当前回答

对于项目中有ExtJS 4的用户,您可以执行以下操作:

Ext.Object.getSize(myobj);

这样做的优点是它可以在所有兼容ExtJS的浏览器上工作(包括InternetExplorer6和InternetExplorer8)。然而,我认为运行时间并不比O(n)好,正如其他建议的解决方案一样。

其他回答

对于项目中包含Undercore.js的用户,您可以执行以下操作:

_({a:'', b:''}).size() // => 2

或功能风格:

_.size({a:'', b:''}) // => 2

标准的Object实现(ES5.1对象内部财产和方法)不要求Object跟踪其键/财产的数量,因此在不显式或隐式迭代其键的情况下,应该没有标准的方法来确定Object的大小。

以下是最常用的替代方案:

1.ECMAScript的Object.keys()

对象.键(obj).长度;通过内部迭代键来计算临时数组并返回其长度。

优点-可读和干净的语法。如果本机支持不可用,则不需要库或自定义代码,除非使用垫片Cons—由于创建阵列而产生的内存开销。

2.基于库的解决方案

本主题其他地方的许多基于库的示例在其库的上下文中都是有用的习惯用法。然而,从性能的角度来看,与完美的无库代码相比,没有什么可获得的,因为所有这些库方法实际上都封装了for循环或ES5 Object.keys(原生或填充)。

3.优化for循环

由于函数调用开销,这种for循环最慢的部分通常是.hasOwnProperty()调用。因此,当我只需要一个JSON对象的条目数时,如果我知道没有代码也不会扩展object.prototype,我就跳过.hasOwnProperty()调用。

否则,通过使k为本地(vark),并使用前缀递增运算符(++count)而不是后缀,可以稍微优化代码。

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

另一个想法依赖于缓存hasOwnProperty方法:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

在给定的环境中,这是否更快是一个基准测试的问题。无论如何,预期的性能增益非常有限。

对于项目中有ExtJS 4的用户,您可以执行以下操作:

Ext.Object.getSize(myobj);

这样做的优点是它可以在所有兼容ExtJS的浏览器上工作(包括InternetExplorer6和InternetExplorer8)。然而,我认为运行时间并不比O(n)好,正如其他建议的解决方案一样。

您可以使用:

Object.keys(objectName).length; 

and

Object.values(objectName).length;

我不知道有什么办法可以做到这一点。然而,为了尽量减少迭代次数,您可以尝试检查__count__的存在,如果它不存在(即,不是Firefox),那么您可以迭代对象并定义它以供以后使用,例如:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

这样,任何支持__count__的浏览器都会使用它,并且只会对那些不支持的浏览器执行迭代。如果计数发生变化而无法执行此操作,则可以始终将其设置为函数:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

这样,任何时候你引用myobj__count__函数将启动并重新计算。