如何获取对象的长度
与数组不同,获取对象的长度一直以来都很棘手。现在终于不用再麻烦了!
Object.keys 返回一个包含对象所有可枚举属性键的数组。之后,你只需调用length
,就搞定了!你就能得到对象的长度了🎉
const object = {one: '1️⃣', two: '2️⃣'};
// Using Lodash
_.size(object); // 2
// Using JavaScript
Object.keys(object).length; // 2
为什么我们不能调用length
对象
你可能会好奇,为什么我们不能length
直接调用我们的对象呢?让我们看看这样做会发生什么:
const object = {one: '1️⃣', two: '2️⃣'};
object.length; // undefined
object.hasOwnProperty('length'); // false
你不能这样做,因为object
没有length
属性。只有string
和arrays
才有length
属性。
const string = 'hello';
const array = [1,2,3];
string.hasOwnProperty('length'); // true
array.hasOwnProperty('length'); // true
什么是可枚举
好吧,我们来讨论另一个话题。我在开头提到过,它会返回一个可枚举Object.keys
属性键的数组。那么,我们来弄清楚这个属性是从哪里来的。enumerable
分配属性
通常,当我们想要向对象添加属性时,我们可能只使用点符号:
const object = {};
object.one = '1️⃣';
console.log(object); // { one: '1️⃣' }
定义属性
或者,我们也可以使用Object.defineProperty
。它接受 3 个参数。我们可以在属性描述符中设置可枚举属性。
Object.defineProperty(object name, property name, property descriptor)
好吧,让我们用这种方法定义一个属性:
const object = {};
Object.defineProperty(
object,
'one', {
value: '1️⃣'
}
);
console.log(object); // {}
// ☝️ Why is it empty? 🤔
嗯……很奇怪。为什么我们的属性没有显示出来呢?🤔 嗯,那是因为当我们这样定义属性时,该enumerable
属性默认是false
。所以如果我们想让它显示出来,我们需要设置true
它。
const object = {};
Object.defineProperty(
object,
'one', {
value: '1️⃣',
enumerable: true // 👈
}
);
console.log(object); // { one: '1️⃣' }
// ☝️ Great, it shows up now!
可枚举默认为 true
让我们回到之前用点符号设置的对象属性示例。为什么它会自动显示出来?那是因为当我们以这种方式赋值属性时,该enumerable
属性会自动设置为true
。
const object = {};
object.one = '1️⃣';
object.propertyIsEnumerable('one'); // true
可枚举摘要
对于我们大多数人来说,在定义属性时很少会用到 enumerable 属性。它只是用来控制我们创建的特定属性在使用 遍历对象时是显示还是隐藏的一种方式Object.keys
。
如果您想了解有关可枚举性的更多信息,我建议您阅读这篇文章《ECMAScript 6 中的可枚举性》。
因此,属性 enumerable 用于隐藏不应被迭代的属性。这就是在 ECMAScript 1 中引入可枚举性的原因。
Axel Rauschmayer 博士,2Ality
Object.keys 与 Object.getOwnPropertyNames
现在您已经了解了enumerable
,让我们介绍另一种您可能认为可以作为获取长度的选项的方法Object.getOwnPropertyNames
。
const object = {one: '1️⃣'};
Object.defineProperty(
object,
'two', {
value: '2️⃣',
enumerable: false
}
);
Object.keys(object); // [ 'one' ]
Object.getOwnPropertyNames(object); // [ 'one', 'two' ]
如您所见,该方法Object.getOwnPropertyNames
将返回所有属性键,而Object.keys
仅返回可枚举属性键。正如我之前提到的,可枚举属性可能由于某种原因被隐藏,所以您可能不想访问它们。因此,这Object.getOwnPropertyName
可能不是您想要用来获取对象长度的方法。
带符号的对象长度
在你默认使用Object.keys
来获取对象长度之前,我想再指出一点。在 ECMAScript 6(ES6)中,引入了一种名为 的新原始数据类型symbol
。你可以将其用作symbol
对象的属性名。
const animal = {
[Symbol('ghost')]: '👻',
turtle: '🐢'
};
symbol
但是当你将 a作为属性名称时,问题就出现了。nor 将Object.keys
不起作用Object.getOwnPropertyNames
。
Object.keys(animal);
// [ 'turtle' ] <-- no symbol
Object.getOwnPropertyNames(animal);
// [ 'turtle' ] <-- no symbol
所以解决方案是使用Object.getOwnPropertySymbols
Object.getOwnPropertySymbols(animal);
// [ Symbol(ghost) ]
现在结合这两种方法,您将获得适当的长度。
const enumerableLength = Object.keys(animal).length;
const symbolLength = Object.getOwnPropertySymbols(animal).length;
const totalObjectLength = enumerableLength + symbolLength;
// 2 <-- 👍
社区意见
@Eugene Karataev:Chrome 会在控制台中显示不可枚举的属性。只是显示方式略有不同,不如可枚举的属性那么醒目。
资源
- MDN Web 文档:Object.keys
- MDN Web 文档:Object.getOwnPropertyNames
- MDN Web 文档:Object.getOwnPropertySymbols
- MDN Web 文档:对象
- 2ality:ES6 中的可枚举性
- 2ality:属性定义与赋值
- Stack Overflow:何时使用 Object.defineProperty
- Stack Overflow:如何使用 JavaScript Object.defineProperty
- Stack Overflow:Object.getOwnPropertyNames 与 Object.keys
- Stack Overflow:JavaScript 对象的长度
感谢阅读❤
打个招呼!Instagram | Twitter | Facebook | Medium |博客