JavaScript中对象的长度:为什么没有简单的.length以及该怎么办?
\n\n您是否曾经有过这样的想法:“为什么数组有.length属性,而对象却没有?”。如果是这样——您并不孤单。“Length of a JavaScript object”这个问题在Stack Overflow上是最热门的问题之一,拥有数千次浏览。这并不奇怪:每个新手迟早都会尝试写obj.length,然后得到undefined。
在本文中,我们将探讨为什么会这样,更重要的是——如何正确计算JavaScript中对象的长度。您将了解4种有效方法,理解何时使用哪种方法,并永远告别对象长度的困惑。
\n\n为什么对象没有length属性?
\n\n这完全取决于对象的本质。数组是一个有序的集合,带有数字索引。JavaScript引擎可以轻松地说:“数组中有5个元素”。而对象是一个无序的“键-值”对集合。理论上,您可以添加属性、删除属性、再次添加——而且顺序无法保证(至少在旧规范中是这样)。
\n\n正是因为这个原因,普通对象没有内置的.length属性。但这并不意味着我们无法计算它。让我们看看如何计算。
方法一:Object.keys()——黄金标准
\n\n最流行且推荐的方法是使用Object.keys()。该方法返回对象自身(非继承)可枚举属性的数组。而数组,正如我们所知,有.length属性。
const user = {\n name: '安娜',\n age: 28,\n city: '莫斯科',\n isAdmin: false\n};\n\nconst length = Object.keys(user).length;\nconsole.log(length); // 4\n\n就是这么简单!您获取一个键的数组,然后取其长度。这种方法在所有现代浏览器和Node.js中都能工作。
\n\nObject.keys()包含什么?
\n\n重要的一点:Object.keys()只返回自身且可枚举的属性。这意味着:
- \n
- 自身——不是通过原型继承的。如果您通过类创建对象或向原型添加方法,它不会出现在结果中。 \n
- 可枚举——那些
enumerable标志设置为true的属性。默认情况下,所有通过赋值创建的属性都是可枚举的。但如果您使用Object.defineProperty()并将enumerable设置为false,这样的属性将被忽略。 \n
包含不可枚举属性的示例:
\n\nconst car = {\n brand: '丰田',\n model: '凯美瑞'\n};\n\nObject.defineProperty(car, 'vin', {\n value: 'JT2BF22KX00000001',\n enumerable: false\n});\n\nconsole.log(Object.keys(car).length); // 2 (vin不被计入)\n\n方法二:Object.values()和Object.entries()
\n\n有时您需要的不仅仅是键的数量,而是值或键值对的数量。这里有两个孪生兄弟可以帮助您:
\n\n- \n
Object.values(obj)——返回值的数组 \n Object.entries(obj)——返回[键, 值]数组的数组 \n
两者都返回数组,因此它们都有.length属性:
const book = {\n title: '大师与玛格丽特',\n author: '布尔加科夫',\n year: 1966\n};\n\nconsole.log(Object.values(book).length); // 3\nconsole.log(Object.entries(book).length); // 3\n\n本质上,数量是相同的,但Object.entries()提供了更多数据,如果您后续需要键和值的话。
方法三:for...in循环(以及如何避免陷阱)
\n\n经典但不太方便的方法是使用for...in循环并手动计数属性:
const person = {\n name: '伊万',\n age: 30\n};\n\nlet count = 0;\nfor (let key in