javascript - javascript如何高效地计算键的数量/ 对象的属性?

  显示原文与译文双语对照的内容

计算对象的键/属性数的最快方法是什么? 不需要迭代对象就可以做到这一点? 换句话说,不做操作


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

( Firefox 提供了一个神奇的__count__ 属性,但它在 4版本的地方被删除。)

时间:

在任何ES5-compatible环境中执行这里操作,例如节点,Chrome,IE 9 +,FF 4 + 或者 Safari 5 +:


Object.keys(obj).length

你可以使用以下代码:


if (!Object.keys) {
 Object.keys = function (obj) {
 var keys = [],
 k;
 for (k in obj) {
 if (Object.prototype.hasOwnProperty.call(obj, k)) {
 keys.push(k);
 }
 }
 return keys;
 };
}

然后,你也可以在旧的浏览器中进行这里操作:


var len = Object.keys(obj).length;

如果你使用的是 Underscore.js,你可以使用 _.size ( 感谢 @douwe): )
_.size(obj)

或者,你也可以使用 _.keys,这可能对某些情况更为清楚:
_.keys(obj).length

我强烈推荐下划线,它是做许多基本事情的严密库。 只要可能,它们都匹配ECMA5并遵从本机实现。

否则我支持 @Avi's 应答。 我编辑的它来将链接添加到多描述doc其中包括 keys()的方法你可以添加要non-ECMA5浏览器。

标准的对象实现( ES5.1 对象内部属性和方法 ) 不需要一个对象来跟踪它的关键点数/属性,因此应该没有标准的方法来确定一个物体的大小,而无需显式或者隐式循环遍历它的键。

下面是最常用的替代方法:

1.Object.keys( )

Object.keys(obj).length; 内部工作方式是 它遍历键指定一个参数临时数组并返回它的长度。

  • 优点 - 可读和简洁的语法。 不需要任何库或者自定义代码,除非本机支持不可用
  • 英镑Cons由于创建数组而造成的内存开销。

2.Library-based解决方案

在本主题的其他library-based示例中,在它们的库上下文中是有用的习惯用法。 从性能角度来看,但是,并没有为了汲取到一个完美no-library代码,因为所有这些库方法相比实际上封装了要么是 for-loop,ES5 Object.keys ( 本机或者 shimmed ) 。

3 。优化 for-loop

这样一个 for-loop 最慢的部分,通常是存在 .hasOwnProperty() 称,由于该函数调用的开销。 所以当我只想要一个JSON对象,我直接跳过了 .hasOwnProperty()的项数,要是我知道代码中没有的东西,我也没有将扩展 Object.prototype

使用prefix-decrement运算符( ++count ) 而不是postfix,否则,你的密码可能是非常轻微的优化通过发出 k 本地( var k ) 和 by.


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;

在给定的环境中,这是否更快或者不重要是一个基准问题。 可能需要非常有限的性能增益。

如果你真的遇到性能问题,我建议将添加/删除属性的调用包装为一个函数,该函数具有递增/递减一个适当命名的( 大小) 属性的函数。

只需计算一次属性的初始数量,然后从那里继续。 如果没有实际的性能问题,请不要费心。 只需将这一小段代码包装在一个函数 getNumberOfProperties(object) 中,就可以完成它。

我不知道怎么做,但是为了使迭代保持最小,你可以尝试检查 __count__ 是否存在,如果它不存在,那么你可以对该对象进行迭代并定义它以备以后使用:


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

这种方式,任何支持 __count__的浏览器都会使用它,而迭代只对那些不支持。 如果计数更改,而你不能这样做,你可以将它的作为函数:


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

每当你引用myobj时。 __count__ 函数将激发并重新计算。

我突然发现这个问题。 它太旧了,但是没有接受的答案,试试:

 
keys(myObj).length

 

我不确定这是多么有效,但它需要最少的代码:)

对于那些包含在项目中的Underscore.js,你可以执行以下操作:


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

或者函数风格:


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

如 Avi http://stackoverflow.com 4889658/1047014


Object.keys(obj).length

将对对象的所有可以枚举属性进行技巧,但也要包括non-enumerable属性,而不是使用 Object.getOwnPropertyNames 。 下面是区别:


var myObject = new Object();

Object.defineProperty(myObject,"nonEnumerableProp", {
 enumerable: false
});
Object.defineProperty(myObject,"enumerableProp", {
 enumerable: true
});

console.log(Object.getOwnPropertyNames(myObject).length);//outputs 2
console.log(Object.keys(myObject).length);//outputs 1

console.log(myObject.hasOwnProperty("nonEnumerableProp"));//outputs true
console.log(myObject.hasOwnProperty("enumerableProp"));//outputs true

console.log("nonEnumerableProp" in myObject);//outputs true
console.log("enumerableProp" in myObject);//outputs true

如前所作为 Object.keys 这里 这个具有相同的浏览器支持

但是,在大多数情况下,你可能不希望在这些类型的操作中包含 nonenumerables,但最好知道差异;

迭代 Object.keys(obj). 亚麻应答长度对于没有绑定函数的对象来说是正确

例如:


obj = {"lol":"what", owo:"pfft"};
Object.keys(obj).length;//should be 2

相对于


arr = [];
obj = {"lol":"what", owo:"pfft"};
obj.omg = function(){
 _.each(obj, function(a){
 arr.push(a);
 });
};
Object.keys(obj).length;//should be 3 becuase it looks like this 
/* obj === {"lol":"what", owo:"pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

避免这里操作的步骤:

  1. 不要将函数放入要计算键数目的对象中

  2. 使用单独的对象或者专门为函数创建一个新对象( 如果你想计算使用 Object.keys(obj).length的文件中有多少函数)

也是我在示例中使用了nodejs的_ 或者下划线模块

可以在这里找到文档 http://underscorejs.org/ 以及它在github上的源代码以及其他各种信息

...