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

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

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


当前回答

以下是三种方法的一些性能测试;

https://jsperf.com/get-the-number-of-keys-in-an-object

对象.keys().length

每秒20735次操作

它非常简单和兼容,运行速度快但成本高昂,因为它创建了一个新的密钥数组,然后将其丢弃。

return Object.keys(objectToRead).length;

循环键

每秒15734次操作

let size=0;
for(let k in objectToRead) {
  size++
}
return size;

它稍微慢一点,但与内存使用量相差甚远,因此如果您对移动或其他小型机器的优化感兴趣,它可能会更好。

使用贴图而不是对象

每秒953839338次操作

return mapToRead.size;

基本上,Map跟踪自己的大小,所以我们只返回一个数字字段。它比任何其他方法都快得多。如果可以控制对象,请将其转换为贴图。

其他回答

要迭代AviFlax的答案,Object.keys(obj).length对于没有绑定函数的对象是正确的。

例子:

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 because it looks like this
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

避免这种情况的步骤:

不要将函数放在要计算键数的对象中使用单独的对象或专门为函数创建新对象(如果要使用object.keys(obj).length计算文件中有多少个函数)

另外,是的,我在示例中使用了Node.js中的_或Undercore.js模块。

文档可以在这里找到,也可以在GitHub和其他各种信息上找到。

最后是一个lodash实现https://lodash.com/docs#size

_.size(对象)

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

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

或功能风格:

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

我解决这个问题的方法是构建我自己的基本列表实现,该列表记录对象中存储了多少项。这很简单。类似于:

function BasicList()
{
   var items = {};
   this.count = 0;

   this.add = function(index, item)
   {
      items[index] = item;
      this.count++;
   }

   this.remove = function (index)
   {
      delete items[index];
      this.count--;
   }

   this.get = function(index)
   {
      if (undefined === index)
        return items;
      else
        return items[index];
   }
}

如前一个答案中所回答的:Object.keys(obj).length

但是:因为我们现在在ES6中有一个真正的Map类,所以我建议使用它,而不是使用对象的财产。

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way

来自Object.defineProperty():

Object.defineProperty(obj、prop、描述符)

您可以将其添加到所有对象:

Object.defineProperty(Object.prototype, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

或单个对象:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

例子:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; // Output: 2

通过这种方式添加,它不会在中显示。。在循环中:

for(var i in myObj) {
    console.log(i + ": " + myObj[i]);
}

输出:

name: John Doe
email: leaked@example.com

注意:它在Internet Explorer 9之前的浏览器中不起作用。