如何有效地计数的钥匙/性的一个目JavaScript?
-
02-07-2019 - |
题
什么是最快的方式来计数的钥匙/性质的对象?它能够这样做没有重复的对象?即没有做
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox提供了一个魔术 __count__
财产,但是,这除去某个地方周围的版本4。)
其他提示
您可以使用此代码:
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
我强烈推荐使用Underscore,它是一个用于执行大量基本操作的紧凑库。只要有可能,它们就会匹配ECMA5并遵循原生实现。
否则我支持@ Avi的回答。我编辑它以添加指向MDC文档的链接,其中包含可以添加到非ECMA5浏览器的keys()方法。
标准的目执行情况(ES5.1象的内部性质和方法)不需要 Object
跟踪其键数/特性,所以应该没有标准的方式确定大小的一个 Object
没有明确或隐含地迭代过其键。
因此,这里是最常用替代品:
1.写的对象。钥匙()
Object.keys(obj).length;
工作 内部 迭代过钥匙来计算一个临时阵列,并返回其长度。
- 优点 -可读性和清洁的语法。没有图书馆或代码定义要求,除了填充程序,如果当地的支持是不可用的
- 弊 -存储器开销,由于建立阵列。
2.图书馆为基础的解决方案
许多基于图书馆的例子在其他地方在这个主题是有用的语在上下文的图书馆。从业绩的观点,然而,没有什么益相比,没有一个完美的图书馆的代码,因为所有这些图书馆的方法实际上封装一个用于环或ES5 Object.keys
(母或匀).
3.优化对环
的 最慢的一部分 这种对于环是一般的 .hasOwnProperty()
呼叫,因为功能呼叫开销。因此,当我只想的条目数量的JSON目的,我只是跳过 .hasOwnProperty()
如果我知道,没有代码有没有也不会延长 Object.prototype
.
否则,你的代码可以稍微通过优化使 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;
这是否是速度更快或不在给定的环境是一个问题的基准。非常有限的性能获得可以预计无论如何。
如果您实际遇到性能问题,我建议使用一个函数来包装调用向对象添加/删除属性的调用,该函数也会增加/减少适当命名的(size?)属性。
您只需要计算一次属性的初始数量,然后从那里继续。如果没有实际的性能问题,请不要打扰。只需将这段代码包装在函数getNumberOfProperties(object)
中并完成它。
我不知道有什么方法可以做到这一点,但为了尽量减少迭代,你可以尝试检查__count__
的存在,如果它不存在(即不是Firefox)那么你可以迭代对象并定义它以供以后使用,例如:
if (myobj.__count__ === undefined) {
myobj.__count__ = ...
}
这样任何支持<=>的浏览器都会使用它,而迭代只会针对那些没有的浏览器执行。如果计数发生变化而您无法执行此操作,则可以始终将其设为一个函数:
if (myobj.__count__ === undefined) {
myobj.__count__ = function() { return ... }
myobj.__count__.toString = function() { return this(); }
}
这样一来,你可以随时引用myobj。<=>这个函数会触发并重新计算。
如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
但是,在大多数情况下,您可能不希望在这些类型的操作中包含非枚举,但了解差异总是很好;)
迭代Avi Flax回答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
计算文件中有多少函数)
醇>
也是的,我在我的例子
中使用了nodejs中的_或下划线模块文档可以在这里找到 http://underscorejs.org/ 以及它在github上的来源和其他各种信息
最后是一个lodash实现 https://lodash.com/docs#size
_.size(obj)
对于那些在项目中包含Underscore.js的人,您可以这样做:
_({a:'', b:''}).size() // => 2
或功能风格:
_.size({a:'', b:''}) // => 2
发件人: https://developer.mozilla。组织/ EN /文档/网络/ JavaScript的/参考/ Global_Objects /对象/ 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 = "leaked@example.com";
myObj.length; //output: 2
添加了这种方式,它不会显示在for..in循环中:
for(var i in myObj) {
console.log(i + ":" + myObj[i]);
}
输出:
name:John Doe
email:leaked@example.com
注意:它不适用于<!> lt; IE9浏览器。
如上所述:Object.keys(obj).length
但是:正如我们现在有一个真正的 Map <在ES6中,我会建议使用它不是使用对象的属性。
const map = new Map();
map.set("key", "value");
map.size; // THE fastest way
我如何解决这个问题是建立我自己的基本列表实现,它记录了对象中存储了多少项。它非常简单。像这样:
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];
}
}
对于那些在他们的项目中有Ext JS 4的人,你可以这样做:
Ext.Object.getSize(myobj);
这样做的好处是它可以在所有与Ext兼容的浏览器上运行(包括IE6-IE8),但是,我认为运行时间并不比O(n)好,与其他建议的解决方案一样。
您可以使用Object.keys(data).length
查找具有关键数据的JSON对象的长度
如果上面的jQuery不起作用,请尝试
$(Object.Item).length
OP未指定对象是否为nodeList,如果是,则可以直接使用 length 方法。例如:
buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen');
我不认为这是可能的(至少在没有使用一些内部的情况下)。而且我认为通过优化它不会获得太多收益。
我尝试将它提供给所有这样的对象:
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
Google Closure对此有一个很好的功能... goog.object.getCount(obj)
您可以使用:
Object.keys(objectName).length;
& Object.values(objectName).length;