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





properties count key (16)


正如Avi Flax所述https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

将为您的对象上的所有可枚举属性执行诀窍,但也会包含非可枚举属性,而不是使用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具有相同的浏览器支持

但是,在大多数情况下,您可能不希望将这些不可枚举类型包含在这些类型的操作中,但知道它们的区别总是很好的;)

计算对象的键/属性数的最快方法是什么? 它可以做到这一点,而无需迭代对象? 即没有做

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

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







对于那些在他们的项目中包含Underscore.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.defineProperty(Object.prototype, "length", {
get() {
    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;
        };
    }
    return Object.keys(this).length;
},});

console.log({"Name":"Joe","Age":26}.length) //returns 2



对于那些在他们的项目中有Ext JS 4的人,你可以这样做:

Ext.Object.getSize(myobj);

这样做的好处是,它可以在所有兼容Ext的浏览器(包括IE6-IE8)上运行,不过,我相信运行时间并不比O(n)好,就像其他建议的解决方案一样。




你可以使用: Object.keys(objectName).length; & Object.values(objectName).length; Object.keys(objectName).length; & 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__函数将触发并重新计算。




要在任何与ES5兼容的环境(例如Node ,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;



如上所述: Object.keys(obj).length

但是:因为我们现在在ES6中有一个真正的Map类,所以我suggest使用它来代替使用对象的属性。

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



如果你真的遇到了性能问题,我会建议使用函数来添加/删除/从对象中删除属性的调用,该函数还会增加/减少一个正确命名的(size?)属性。

你只需要计算一次属性的初始数量并从那里继续。 如果没有实际的性能问题,请不要打扰。 只需在函数getNumberOfProperties(object)包装这些代码并完成它。




来自: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyhttps://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty(obj,prop,descriptor)

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

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 = "[email protected]";
myObj.length; //output: 2

补充说,它不会显示在for..in循环中:

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

输出:

name:John Doe
email:[email protected]

注意:它在<IE9浏览器中不起作用。




如果上面的jQuery不起作用,然后尝试

$(Object.Item).length



我在一段时间后写了一篇博文,解释了闭包。这就是我所说的关于你想要一个闭包的原因

闭包是一种让函数具有持久的私有变量的方法 - 也就是说,只有一个函数知道的变量,它可以跟踪之前运行的信息。

从这个意义上讲,它们让函数有点像具有私有属性的对象。

全文:

那么封闭东西是什么?





javascript performance properties count key