探秘 JavaScript 对象长度的那些事儿

2024-12-17

一、引言

图片5.jpg

简述

在 JavaScript 的世界里呀,大家都知道获取数组或者字符串的长度挺简单的,直接用 .length 属性就行啦,比如对于数组 let arr = [1, 2, 3];,那 arr.length 就能轻松得到它的长度为 3;字符串 let str = 'hello';,str.length 也能马上知晓字符个数是 5。可是呢,一涉及到对象长度的获取,就没那么直观了呀。对象可不像数组那样有个现成的属性可以直接调用获取长度呢。那到底该怎么去知晓一个 JavaScript 对象里包含了多少属性,也就是它的 “长度” 呢?其实呀,这里面有多种方法可供选择,而且不同的方法在面对诸如可枚举属性、不可枚举属性以及 Symbol 类型属性等情况时,各有各的特点和适用场景呢。接下来,咱们就详细地探讨一下获取 JavaScript 对象长度的这些方法以及相关的应用场景,相信这会让你对 JavaScript 对象的操作有更深的理解哦,一起往下看吧。

二、js 对象长度的基本概念

普通对象与有序集合的差异

在 JavaScript 里呀,普通对象不能像数组或者字符串那样直接用 length 属性来获取它所谓的 “长度” 哦。这是为啥呢?因为普通对象它并不是有序集合呀。像数组,里面的元素是按照特定的顺序依次排列的,比如 let arr = [1, 2, 3];,每个元素都有对应的索引位置,所以通过 arr.length 就能很明确地知道元素的个数是 3 个。字符串也是同理呀,let str = 'hello';,字符按照先后顺序组成了这个字符串,用 str.length 就能知晓字符个数是 5 个呢。可普通对象呢,它里面的属性是以键值对的形式存在的,并没有像数组那样严格的顺序概念,属性之间不存在像数组元素那种先后顺序的关联性,所以没办法直接用 length 去获取它包含属性的数量啦,这就是普通对象和有序集合在长度概念上的本质区别哦。

不同类型对象获取长度的方法

使用 Object.keys ()

Object.keys() 这个方法在获取对象长度方面挺常用的呢。它的作用呀,是返回一个对象自身(也就是不包括继承属性哦)可枚举自有属性的键的数组。拿到这个数组后,我们就可以借助数组本身的 length 属性来得到对象的长度啦。给大家举个例子吧,比如说有这样一个对象 let obj = {name: 'John', age: 30, city: 'New York'};,我们使用 Object.keys(obj) ,它就会返回 ["name", "age", "city"] 这样一个数组,这个数组里的元素就是对象 obj 的可枚举自有属性的键啦。然后再通过 Object.keys(obj).length 来获取这个数组的长度,在这里返回的结果就是 3,也就意味着对象 obj 包含了 3 个可枚举的自有属性哦,是不是挺方便的呀。

使用 for...in 循环

还有一种获取对象长度的办法就是利用 for...in 循环啦。这个循环可以用来遍历对象所有的键哦,我们可以在遍历的过程中进行计数,从而得到对象的长度呢。不过这里有个要点要注意哦,那就是为了确保只遍历对象自身的自有属性,我们得使用 hasOwnProperty 这个方法来进行判断呀,不然可能连继承来的属性也一起遍历进去了,那就不准确啦。在这个例子里呀,for...in 循环会逐个去访问对象 myObj 的键,通过 hasOwnProperty 判断是自有属性后,计数器 count 就加 1,最后就能得到对象自有属性的个数啦,在这里输出的结果就是 2 哦。这种方式在一些需要全面考虑对象自有属性情况的场景中就挺适用的呢。

使用 Object.getOwnPropertyNames ()

Object.getOwnPropertyNames() 这个方法也可以用来获取对象的长度哦。它会返回一个包含对象所有键名的数组(不过这里要注意啦,是除了 Symbol 属性外的所有自有属性哦),然后我们再用这个数组的 length 属性去获取对象的长度就好啦。它和 Object.keys() 是有不同之处的哦,Object.keys() 只返回可枚举的自有属性的键组成的数组,而 Object.getOwnPropertyNames() 除了可枚举的自有属性键之外,还会把不可枚举的自有属性键也包含进来(只要不是 Symbol 属性就行)。在这个例子里呀,通过 Object.keys(exampleObj).length 得到的结果是 1,因为它只统计可枚举的属性 visibleProp ;而通过 Object.getOwnPropertyNames(exampleObj).length 得到的结果是 2,因为它把不可枚举的 hiddenProp 也包含进去统计了哦。所以大家可以根据实际需求,来选择使用 Object.keys() 还是 Object.getOwnPropertyNames() 去获取对象的长度啦。

三、ES6 相关方法与特殊情况

Object.keys () 与 Object.values () 在 ES6 中的特点

在 ES6 里呀,Object.keys() 和 Object.values() 这两个方法在遍历对象的时候,会忽略继承属性哦。这一点和之前一些操作对象属性的情况是有所不同的呢。比如说我们有一个对象,它可能继承了其他对象的一些属性,但是使用 Object.keys() 去获取它的键组成的数组时,只会包含它自身的可枚举自有属性对应的键哦,继承来的那些属性就不会出现在这个数组当中啦。同样的,Object.values() 在获取对象自身可遍历属性的键值组成的数组时,也会把继承属性排除在外呢。那这样的特点对于我们获取对象长度来说,操作上就会有相应的变化啦。以往在考虑继承属性干扰的情况下,我们可能还得通过像 hasOwnProperty 这类方法去进行额外的判断和筛选,才能准确统计出对象自身属性的个数,也就是对象的长度呀。但在 ES6 里,利用 Object.keys() 得到的数组,我们可以直接通过这个数组的 length 属性去获取对象自身可枚举属性的数量,也就是对象长度啦,变得更加方便简洁了呢。在这个例子中,childObj 继承了 parentObj 的属性,可通过 Object.keys(childObj) 得到的数组里就只有 ["childProp1", "childProp2"] ,其长度为 2,也就准确地反映了 childObj 自身可枚举属性的个数啦,是不是很容易就能获取到对象长度了呀,这就是 ES6 里这些方法给我们带来的便利之处哦,大家要好好掌握呢。

涉及 Symbol 属性的对象长度获取

当对象包含 Symbol 属性时呀,像 Object.keys() 和 Object.getOwnPropertyNames() 这两个方法就存在一定的局限性啦。因为 Object.keys() 它只返回对象自身可枚举的自有属性的键组成的数组,本身就不包含 Symbol 属性相关的内容呢;而 Object.getOwnPropertyNames() 虽然会返回对象除了 Symbol 属性外的所有自有属性键组成的数组,也就是它也没法把 Symbol 属性考虑进去统计对象长度哦。这时候呢,就需要用到 Object.getOwnPropertySymbols() 这个方法啦。它的作用就是返回一个包含对象所有 Symbol 类型自有属性名的数组哦。那我们如果要获取包含 Symbol 属性在内的对象的完整长度,就可以先通过 Object.getOwnPropertyNames() 获取普通自有属性键组成的数组,再通过 Object.getOwnPropertySymbols() 获取 Symbol 属性名组成的数组,然后把这两个数组的长度相加,就能得到这个对象完整的属性个数,也就是对象的长度啦。在这个例子中呀,对象 symbolObj 既有普通的自有属性 normalProp ,又有 Symbol 类型的属性 sym1 和 sym2 。通过 Object.getOwnPropertyNames(symbolObj) 得到普通属性键数组长度为 1,通过 Object.getOwnPropertySymbols(symbolObj) 得到 Symbol 属性名数组长度为 2,两者相加得到总长度为 3,这样就准确获取到了包含特殊 Symbol 属性的这个对象的完整长度啦。所以呀,大家在遇到对象有 Symbol 属性这种特殊情况时,可别忘了用 Object.getOwnPropertySymbols() 这个方法来准确获取对象长度哦。

四、js 对象长度在实际开发中的应用

控制对象元素数量

在实际开发中呀,js 对象长度的应用场景可不少呢,就比如说控制对象元素数量这一点吧。咱们可以想象一个生活中的场景,比如控制书包装书本的数量。假设我们用一个对象来代表书包,对象的属性就是每一本书那怎么知道书包里已经装了几本书,也就是这个对象包含了几个属性呢?这时候就可以用上咱们前面讲过的获取对象长度的方法啦,比如通过 Object.keys(schoolBag).length 就能得到书包里书本属性的个数,在这里返回的就是 3,代表装了 3 本书呢。通过这样的方式,就能很方便地基于对象长度来进行逻辑判断,决定是否可以添加新的元素啦。其实呀,在很多类似的场景中,只要涉及到对对象元素数量有一定限制,需要判断是否满足条件的情况,都可以利用获取对象长度的方法来巧妙地处理哦,大家可以联想一下自己开发过程中遇到的类似场景呀。

为对象添加长度属性

除了上面说的利用现有方法去获取对象长度用于判断等操作外,我们还可以主动为对象添加长度属性哦,这在某些情况下也是很实用的呢。在 JavaScript 中,我们可以通过 Object.defineProperty 方法来为对象添加长度属性呀。通过这样的设置,我们就给 myObject 添加了一个名为 length 的属性啦,而且可以通过 myObject.length 来获取它的长度值,在这里就是 2 哦。不过要注意呀,为对象添加的这个长度属性并不会自动更新哦。什么意思呢?就是说如果之后对象的属性发生了变化,比如又新增或者删除了某个属性,那这个长度属性的值不会跟着自动改变的,还是需要我们手动去更新它的值呢所以呀,在使用为对象添加长度属性这个操作时,要时刻记得它不能自动更新这一特点,根据实际情况适时手动去维护长度属性的值,这样才能保证它的准确性,让它在我们的开发中发挥出应有的作用,比如方便地知晓对象当前属性的数量等情况呢。

五、总结

回顾重点方法

在前面的内容中,我们详细介绍了多种获取 JavaScript 对象长度的方法呢。首先是 Object.keys() 方法,它能够返回一个对象自身可枚举自有属性的键的数组,我们再借助这个数组的 length 属性,就能知晓对象的长度啦,像对于 let obj = {name: 'John', age: 30, city: 'New York'}; 这样的对象,通过 Object.keys(obj).length 就能得到其长度为 3 哦。还有 for...in 循环的方式呀,利用它来遍历对象所有的键,不过要配合 hasOwnProperty 方法进行判断,确保只统计对象自身的自有属性,通过在遍历过程中计数,从而得到对象的长度呢,例如特定的对象示例中可以通过这种方式准确算出自有属性的个数。Object.getOwnPropertyNames() 这个方法也不容忽视呀,它会返回包含对象所有键名(除了 Symbol 属性外的所有自有属性)的数组,接着利用该数组的 length 属性获取对象长度,而且它和 Object.keys() 的区别在于,它除了可枚举的自有属性键之外,还会把不可枚举的自有属性键也包含进来哦,不同场景下可以按需选用呢。在 ES6 相关情况里,Object.keys() 和 Object.values() 在遍历对象时会忽略继承属性,让获取对象自身可枚举属性的长度变得更加便捷啦。而当对象包含 Symbol 属性时,就得用上 Object.getOwnPropertySymbols() 方法啦,它可以返回包含对象所有 Symbol 类型自有属性名的数组,结合 Object.getOwnPropertyNames() 获取的普通自有属性键组成的数组,将二者长度相加,就能得到包含 Symbol 属性对象的完整长度了哦。

强调适用场景

不同的获取 JavaScript 对象长度的方法,有着各自适合的应用场景呢。如果只是想获取对象自身可枚举的自有属性长度,那 Object.keys() 方法就是个不错的选择呀,它简洁高效,像在很多常规的对象属性统计场景中,只要不涉及不可枚举属性和 Symbol 属性的情况,用它就挺合适的。要是需要把对象除 Symbol 属性外的所有自有属性都统计进来,包括那些不可枚举的自有属性,这时候 Object.getOwnPropertyNames() 方法就能派上用场了哦,例如在一些需要全面了解对象自有属性个数,不管其是否可枚举的业务逻辑处理中就可以考虑使用它呢。而对于 for...in 循环获取对象长度的方式,由于它可以遍历到对象及其原型链中所有可枚举的属性(当然配合 hasOwnProperty 能精准到自有属性),所以在需要综合考虑各类可枚举属性情况,比如排查继承属性干扰等场景下可以使用哦,不过相对来说代码逻辑会稍微复杂一点啦。在 ES6 环境下,当要处理继承属性并且只需关注对象自身可枚举属性长度时,Object.keys() 和 Object.values() 的便利性就体现出来了,能让我们更轻松地获取相应长度呢。最后,一旦对象包含了 Symbol 属性,要想得到完整准确的对象长度,可别忘了使用 Object.getOwnPropertySymbols() 配合 Object.getOwnPropertyNames() 的方式呀,在涉及这种特殊数据类型属性的对象长度统计时,它就是准确获取长度的关键啦,比如在一些复杂的数据结构或者特定的