如何在JavaScript中有效地计算对象的键/属性数?
计算对象的关键点/属性数的最快方法是什么?是否可以在不迭代对象的情况下执行此操作?i、 e.不采取行动如何在JavaScript中有效地计算对象的键/属性数?,javascript,performance,properties,count,key,Javascript,Performance,Properties,Count,Key,计算对象的关键点/属性数的最快方法是什么?是否可以在不迭代对象的情况下执行此操作?i、 e.不采取行动 var count = 0; for (k in myobj) if (myobj.hasOwnProperty(k)) count++; (Firefox确实提供了一个神奇的\uuuuuu count\uuuuuuu属性,但它在版本4的某个地方被删除了。)我认为这是不可能的(至少在不使用一些内部构件的情况下是不可能的)。我认为优化这个不会有什么好处。如果您实际遇到性能问题,我建议使用一个函
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox确实提供了一个神奇的
\uuuuuu count\uuuuuuu
属性,但它在版本4的某个地方被删除了。)我认为这是不可能的(至少在不使用一些内部构件的情况下是不可能的)。我认为优化这个不会有什么好处。如果您实际遇到性能问题,我建议使用一个函数来包装向对象添加/删除属性的调用,该函数还可以增加/减少适当命名的(大小?)属性
您只需计算一次初始属性数,然后再继续。如果没有实际的性能问题,就不用麻烦了。只需将这段代码包装在一个函数
getNumberOfProperties(object)
中,然后就可以使用它了。我不知道有什么方法可以做到这一点,但是为了将迭代次数降到最低,你可以试着检查\uuuuuu count\uuuuuu>是否存在,如果它不存在(即不是Firefox)然后您可以迭代对象并定义它以供以后使用,例如:
if (myobj.__count__ === undefined) {
myobj.__count__ = ...
}
这样,任何支持\uuuuuu count\uuuuuu
的浏览器都会使用它,并且只会对那些不支持的浏览器执行迭代。如果计数发生变化,而您无法执行此操作,则始终可以将其设置为函数:
if (myobj.__count__ === undefined) {
myobj.__count__ = function() { return ... }
myobj.__count__.toString = function() { return this(); }
}
通过这种方式,您可以在任何时候引用myobj。\uuuuuu count\uuuuuuu
该函数将启动并重新计算。要在任何ES5兼容环境(如Chrome、IE 9+、Firefox 4+或Safari 5+)中执行此操作,请执行以下操作:
Object.keys(obj).length
- (包括可添加到非ES5浏览器的方法)
您可以使用以下代码:
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;
如果您正在使用,您可以使用(谢谢@douwe):
尺寸(obj)
或者,您也可以使用对某些人来说更清晰的选项:
\按键(obj).长度
我强烈推荐下划线,它是一个用于做很多基本事情的紧凑库。只要有可能,它们就匹配ECMA5并遵从本机实现
否则我支持@Avi的答案。我编辑它是为了添加一个指向MDC文档的链接,其中包括可以添加到非ECMA5浏览器中的keys()方法。我解决这个问题的方法是构建我自己的基本列表实现,该列表记录了对象中存储了多少项。这很简单。大概是这样的:
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
对于项目中包含下划线.js的用户,您可以执行以下操作:
Ext.Object.getSize(myobj);
。({a:'',b:''})。大小()/=>2
或功能性风格:
\uu0.size({a:'',b:''})/=>2
对于那些在项目中有Ext JS 4的用户,您可以执行以下操作:
Ext.Object.getSize(myobj);
这样做的好处是,它可以在所有兼容Ext的浏览器(包括IE6-IE8)上运行,但是,我相信运行时间并不比O(n)好,就像其他建议的解决方案一样。如果上面的jQuery不起作用,那么试试看
$(Object.Item).length
如Avi Flax所述
将对对象上的所有可枚举属性执行此操作,但为了也包括不可枚举属性,您可以使用对象.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
但是,在大多数情况下,您可能不希望在这些类型的操作中包含非数值项,但知道它们之间的区别总是好的;) 标准对象实现()不需要对象
来跟踪其键/属性的数量,因此在不显式或隐式迭代其键的情况下,应该没有确定对象
大小的标准方法
以下是最常用的替代方案:
1.ECMAScript的Object.keys()
Object.key(obj.length)
通过对键进行内部迭代来计算临时数组并返回其长度
- 优点可读且清晰的语法。如果本机支持不可用,则不需要库代码或自定义代码,但需要垫片
- Cons-由于创建阵列而导致的内存开销
2.基于库的解决方案
本主题其他地方的许多基于库的示例在其库的上下文中都是有用的习惯用法。但是,从性能的角度来看,与完美的无库代码相比,没有任何好处,因为所有这些库方法实际上都封装了for循环或ES5Object.keys
(原生或填充)
3.优化for循环
由于函数调用开销,这种for循环最慢的部分通常是.hasOwnProperty()
调用。因此,当我只需要一个JSON对象的条目数时,如果我知道没有代码没有也不会扩展对象.prototype
,我就跳过.hasOwnProperty()
调用
否则,通过将k
设为本地(var k
),并使用前缀增量运算符(++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;
在给定的环境中,这是否更快是一个基准测试的问题。无论如何,预期的性能增益非常有限。在Avi Flax answer 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 because it looks like this
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */
避免这种情况的步骤:
不要将函数放入要计算其中键数的对象中
使用单独的对象或专门为函数创建一个新对象(如果要使用object.keys(obj.length)计算文件中有多少函数)
也是的,我在示例中使用了nodejs中的uu或下划线模块<
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
const map = new Map();
map.set("key", "value");
map.size; // THE fastest way
Object.keys(objectName).length;
Object.values(objectName).length;
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
buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen');
return Object.keys(objectToRead).length;
let size=0;
for(let k in objectToRead) {
size++
}
return size;
return mapToRead.size;