如何计算JavaScript对象的属性数量?

187

假设我在 JavaScript 中有以下对象:

var object = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}; 

我如何找出对象中存在多少个值?


8
等一下!JS 没有元组和字典。那被称为对象(用文字符号表示),尽管它看起来像 Python 字典。然而,在上面的例子中,你该如何称呼元组? - Ionuț G. Stan
1
是的。它是重复的,因为我不知道如何正确地提问。我们可以将其标记为重复。 - Eugeniu Torica
31
很简单,各位:Object.keys(myObject).length,详见我的帖子。 - deadrunk
有另一个答案似乎更合适,您是否考虑重新选择接受的答案? - Qwerty
@deadrunk,你应该将它发布为答案,它比被接受的那个更好... - eduyayo
显示剩余3条评论
8个回答

567
你可以使用这个简单的代码来实现这个目标:
Object.keys(myObject).length

19
@Andrew,我不会说“远非完全支持”,我会说不支持IE8及以下版本。此外,Polyfill - hitautodestruct
24
如果社区可以关闭问题,那么社区也应该能够更改正确答案。 - Case
14
这绝对是正确的答案,简单而优雅!@Iscariot +1:完全同意! - tanou
13
这应该是被接受的答案,我认为“但它在IE8中不起作用”这个论点并不能成为任何借口。尝试支持它唯一可能的原因是行业仍在使用Windows XP。在这种情况下,我认为切换到另一个浏览器是更好的选择,继续开发和支持IE8只会是一条毫无意义的漫长之路,如果你的代码只在IE中运行,那么你将不得不在某个时候重新编写它。 - Morvael
7
如果你想编写代码以迎合技术落后地区,请随意这样做。但我希望你也能为2400波特连接优化所有代码。享受生活在过去的感觉吧。 - Darth Egregious
显示剩余7条评论

113

没有简单的答案,因为每个JavaScript对象都继承自Object,它自动包含许多属性,而你得到的确切属性集取决于特定解释器和在你之前执行的代码。所以,你需要将你定义的属性与那些你“免费”获得的属性分开。

这里有一种方法:

var foo = {"key1": "value1", "key2": "value2", "key3": "value3"};
Object.prototype.foobie = 'bletch'; // add property to foo that won't be counted

var count = 0;
for (var k in foo) {
    if (foo.hasOwnProperty(k)) {
       ++count;
    }
}
alert("Found " + count + " properties specific to foo");

第二行展示了其他代码如何向所有Object的派生对象中添加属性。如果在循环内部删除hasOwnProperty()检查,则属性计数至少会增加到4个。在一个包含除此代码之外的其他JavaScript的页面上,如果该其他代码也修改Object原型,则它可能会更高于4个。

3
不应使用空对象来访问Object.prototype。只需使用Object.prototype.hasOwnProperty.call(foo, k)。 - Eli Grey
1
为什么不直接使用foo.hasOwnProperty(k)呢?我有遗漏什么吗?我的意思是即使JavaScript类型派生自Object.prototype,它也会有一个hasOwnProperty()方法。 - bucabay
@Elijah:我不明白我做的有什么问题,但是没错,你的方法也应该可以。 - Warren Young
2
@bucabay:测试的目的是找到“foo”具有而其他对象派生物没有的属性。删除测试可能会很有启发性,看看计数会达到多少。你会发现它会达到几十个。仅举一个例子,你会发现“foo”和“empty”中都有对“hasOwnProperty()”的引用,因为“成员函数”也是对象的属性,而不仅仅是一些其他语言中的数据。 - Warren Young
@WarrenYoung 语句 empty.hasOwnProperty(k) 总是为 FALSE,因为空对象没有直接属性。foo.hasOwnProperty(k) 只会返回直接属性,而不包括从 Object.prototype 继承的属性。 - bucabay
显示剩余2条评论

51

使用非常实用的underscore库:_.keys(obj).length 可以获取对象的键值对数量。


我正在使用它,非常酷。谢谢Alexander。 - Wolf87
9
使用underscore.js,您可以使用_.size(obj)函数来计算对象的大小。 - GijsjanB

12

您可以迭代对象以获取键或值:

function numKeys(obj)
{
    var count = 0;
    for(var prop in obj)
    {
        count++;
    }
    return count;
}

看起来像是“拼写错误”,但是我想指出你的示例代码存在无效语法,应该改为:

var object = {"key1":"value1","key2":"value2","key3":"value3"};


11
 var miobj = [
  {"padreid":"0", "sw":"0", "dtip":"UNO", "datos":[]},
  {"padreid":"1", "sw":"0", "dtip":"DOS", "datos":[]}
 ];
 alert(miobj.length) //=== 2

但是

 alert(miobj[0].length) //=== undefined

这个函数非常好

Object.prototype.count = function () {
    var count = 0;
    for(var prop in this) {
        if(this.hasOwnProperty(prop))
            count = count + 1;
    }
    return count;
}

alert(miobj.count()) // === 2
alert(miobj[0].count()) // === 4

4
扩展原生对象是一种不良实践。请勿这样做。 - jzfgo
当我使用这段代码时,Bootstrap下拉菜单无法正常工作。 - Satish Kumar sonker

5

如果可用,此函数将利用Mozilla的__count__属性,因为它比迭代每个属性更快。

function countProperties(obj) {
  var count = "__count__",
  hasOwnProp = Object.prototype.hasOwnProperty;

  if (typeof obj[count] === "number" && !hasOwnProp.call(obj, count)) {
    return obj[count];
  }
  count = 0;
  for (var prop in obj) {
    if (hasOwnProp.call(obj, prop)) {
      count++;
    }
  }
  return count;
};

countProperties({
  "1": 2,
  "3": 4,
  "5": 6
}) === 3;

请注意,这个属性在 Firefox 4 中被弃用,并在不久之后被移除,因此在过去几年中未出现在任何浏览器中。 - Sasha Chedygov

4
编辑:这样做会导致jquery错误发生,以及其他一些不便之处。你不应该使用它:(也许如果能添加私有方法而不是公共属性函数,那么这将是可以的,但现在没有时间)。社区维基认证
不要使用:
尽管javascript默认情况下的对象没有计数函数,但类很容易扩展,我们可以自己添加它:
Object.prototype.count = function () {
    var count = 0;
    for(var prop in this) {
        if(this.hasOwnProperty(prop))
            count = count + 1;
    }
    return count;
}

这样,之后就能执行。
var object = {'key1': 'val1', 'key2':'val2', 'key3':'val3'};
console.log(object.count()); // 3

作为结论,如果你想在对象中使用计数功能,需要从代码块1中复制代码,并在执行时间早期粘贴它(在调用计数之前)。
如果这对你有帮助,请告诉我!
敬礼, Pedro

嗨。我已经使用这个工具一段时间了,没有遇到任何问题...唯一的问题是,如果你在实现此属性后循环对象,它会执行额外的循环。如果有人能找到一个解决方法,那就太好了。 - Pedro
咦?为什么不行?有人可能会修复它。 - Pedro
在我看来,扩展标准类型并不是最好的想法。 - deadrunk
我同意,但是我们的 Ruby 社区可能不会同意。;) - Pedro

-4

虽然它不是一个“真正的对象”,但你总可以像这样做:

var foo = [
  {Key1: "key1"},
  {Key2: "key2"},
  {Key3: "key3"}
];

alert(foo.length); // === 3

我们正在尝试获取属性的长度。因此,在您的情况下,结果应该只有1。 - Santosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接