探秘 JavaScript 對(duì)象長(zhǎng)度的那些事兒
2024-12-17 09:12:24
一、引言

簡(jiǎn)述
在 JavaScript 的世界里呀,大家都知道獲取數(shù)組或者字符串的長(zhǎng)度挺簡(jiǎn)單的,直接用 .length 屬性就行啦,比如對(duì)于數(shù)組 let arr = [1, 2, 3];,那 arr.length 就能輕松得到它的長(zhǎng)度為 3;字符串 let str = 'hello';,str.length 也能馬上知曉字符個(gè)數(shù)是 5??墒悄兀簧婕暗綄?duì)象長(zhǎng)度的獲取,就沒那么直觀了呀。對(duì)象可不像數(shù)組那樣有個(gè)現(xiàn)成的屬性可以直接調(diào)用獲取長(zhǎng)度呢。那到底該怎么去知曉一個(gè) JavaScript 對(duì)象里包含了多少屬性,也就是它的 “長(zhǎng)度” 呢?其實(shí)呀,這里面有多種方法可供選擇,而且不同的方法在面對(duì)諸如可枚舉屬性、不可枚舉屬性以及 Symbol 類型屬性等情況時(shí),各有各的特點(diǎn)和適用場(chǎng)景呢。接下來,咱們就詳細(xì)地探討一下獲取 JavaScript 對(duì)象長(zhǎng)度的這些方法以及相關(guān)的應(yīng)用場(chǎng)景,相信這會(huì)讓你對(duì) JavaScript 對(duì)象的操作有更深的理解哦,一起往下看吧。
二、js 對(duì)象長(zhǎng)度的基本概念
普通對(duì)象與有序集合的差異
在 JavaScript 里呀,普通對(duì)象不能像數(shù)組或者字符串那樣直接用 length 屬性來獲取它所謂的 “長(zhǎng)度” 哦。這是為啥呢?因?yàn)槠胀▽?duì)象它并不是有序集合呀。像數(shù)組,里面的元素是按照特定的順序依次排列的,比如 let arr = [1, 2, 3];,每個(gè)元素都有對(duì)應(yīng)的索引位置,所以通過 arr.length 就能很明確地知道元素的個(gè)數(shù)是 3 個(gè)。字符串也是同理呀,let str = 'hello';,字符按照先后順序組成了這個(gè)字符串,用 str.length 就能知曉字符個(gè)數(shù)是 5 個(gè)呢??善胀▽?duì)象呢,它里面的屬性是以鍵值對(duì)的形式存在的,并沒有像數(shù)組那樣嚴(yán)格的順序概念,屬性之間不存在像數(shù)組元素那種先后順序的關(guān)聯(lián)性,所以沒辦法直接用 length 去獲取它包含屬性的數(shù)量啦,這就是普通對(duì)象和有序集合在長(zhǎng)度概念上的本質(zhì)區(qū)別哦。
不同類型對(duì)象獲取長(zhǎng)度的方法
使用 Object.keys ()
Object.keys() 這個(gè)方法在獲取對(duì)象長(zhǎng)度方面挺常用的呢。它的作用呀,是返回一個(gè)對(duì)象自身(也就是不包括繼承屬性哦)可枚舉自有屬性的鍵的數(shù)組。拿到這個(gè)數(shù)組后,我們就可以借助數(shù)組本身的 length 屬性來得到對(duì)象的長(zhǎng)度啦。給大家舉個(gè)例子吧,比如說有這樣一個(gè)對(duì)象 let obj = {name: 'John', age: 30, city: 'New York'};,我們使用 Object.keys(obj) ,它就會(huì)返回 ["name", "age", "city"] 這樣一個(gè)數(shù)組,這個(gè)數(shù)組里的元素就是對(duì)象 obj 的可枚舉自有屬性的鍵啦。然后再通過 Object.keys(obj).length 來獲取這個(gè)數(shù)組的長(zhǎng)度,在這里返回的結(jié)果就是 3,也就意味著對(duì)象 obj 包含了 3 個(gè)可枚舉的自有屬性哦,是不是挺方便的呀。
使用 for...in 循環(huán)
還有一種獲取對(duì)象長(zhǎng)度的辦法就是利用 for...in 循環(huán)啦。這個(gè)循環(huán)可以用來遍歷對(duì)象所有的鍵哦,我們可以在遍歷的過程中進(jìn)行計(jì)數(shù),從而得到對(duì)象的長(zhǎng)度呢。不過這里有個(gè)要點(diǎn)要注意哦,那就是為了確保只遍歷對(duì)象自身的自有屬性,我們得使用 hasOwnProperty 這個(gè)方法來進(jìn)行判斷呀,不然可能連繼承來的屬性也一起遍歷進(jìn)去了,那就不準(zhǔn)確啦。在這個(gè)例子里呀,for...in 循環(huán)會(huì)逐個(gè)去訪問對(duì)象 myObj 的鍵,通過 hasOwnProperty 判斷是自有屬性后,計(jì)數(shù)器 count 就加 1,最后就能得到對(duì)象自有屬性的個(gè)數(shù)啦,在這里輸出的結(jié)果就是 2 哦。這種方式在一些需要全面考慮對(duì)象自有屬性情況的場(chǎng)景中就挺適用的呢。
使用 Object.getOwnPropertyNames ()
Object.getOwnPropertyNames() 這個(gè)方法也可以用來獲取對(duì)象的長(zhǎng)度哦。它會(huì)返回一個(gè)包含對(duì)象所有鍵名的數(shù)組(不過這里要注意啦,是除了 Symbol 屬性外的所有自有屬性哦),然后我們?cè)儆眠@個(gè)數(shù)組的 length 屬性去獲取對(duì)象的長(zhǎng)度就好啦。它和 Object.keys() 是有不同之處的哦,Object.keys() 只返回可枚舉的自有屬性的鍵組成的數(shù)組,而 Object.getOwnPropertyNames() 除了可枚舉的自有屬性鍵之外,還會(huì)把不可枚舉的自有屬性鍵也包含進(jìn)來(只要不是 Symbol 屬性就行)。在這個(gè)例子里呀,通過 Object.keys(exampleObj).length 得到的結(jié)果是 1,因?yàn)樗唤y(tǒng)計(jì)可枚舉的屬性 visibleProp ;而通過 Object.getOwnPropertyNames(exampleObj).length 得到的結(jié)果是 2,因?yàn)樗巡豢擅杜e的 hiddenProp 也包含進(jìn)去統(tǒng)計(jì)了哦。所以大家可以根據(jù)實(shí)際需求,來選擇使用 Object.keys() 還是 Object.getOwnPropertyNames() 去獲取對(duì)象的長(zhǎng)度啦。
三、ES6 相關(guān)方法與特殊情況
Object.keys () 與 Object.values () 在 ES6 中的特點(diǎn)
在 ES6 里呀,Object.keys() 和 Object.values() 這兩個(gè)方法在遍歷對(duì)象的時(shí)候,會(huì)忽略繼承屬性哦。這一點(diǎn)和之前一些操作對(duì)象屬性的情況是有所不同的呢。比如說我們有一個(gè)對(duì)象,它可能繼承了其他對(duì)象的一些屬性,但是使用 Object.keys() 去獲取它的鍵組成的數(shù)組時(shí),只會(huì)包含它自身的可枚舉自有屬性對(duì)應(yīng)的鍵哦,繼承來的那些屬性就不會(huì)出現(xiàn)在這個(gè)數(shù)組當(dāng)中啦。同樣的,Object.values() 在獲取對(duì)象自身可遍歷屬性的鍵值組成的數(shù)組時(shí),也會(huì)把繼承屬性排除在外呢。那這樣的特點(diǎn)對(duì)于我們獲取對(duì)象長(zhǎng)度來說,操作上就會(huì)有相應(yīng)的變化啦。以往在考慮繼承屬性干擾的情況下,我們可能還得通過像 hasOwnProperty 這類方法去進(jìn)行額外的判斷和篩選,才能準(zhǔn)確統(tǒng)計(jì)出對(duì)象自身屬性的個(gè)數(shù),也就是對(duì)象的長(zhǎng)度呀。但在 ES6 里,利用 Object.keys() 得到的數(shù)組,我們可以直接通過這個(gè)數(shù)組的 length 屬性去獲取對(duì)象自身可枚舉屬性的數(shù)量,也就是對(duì)象長(zhǎng)度啦,變得更加方便簡(jiǎn)潔了呢。在這個(gè)例子中,childObj 繼承了 parentObj 的屬性,可通過 Object.keys(childObj) 得到的數(shù)組里就只有 ["childProp1", "childProp2"] ,其長(zhǎng)度為 2,也就準(zhǔn)確地反映了 childObj 自身可枚舉屬性的個(gè)數(shù)啦,是不是很容易就能獲取到對(duì)象長(zhǎng)度了呀,這就是 ES6 里這些方法給我們帶來的便利之處哦,大家要好好掌握呢。
涉及 Symbol 屬性的對(duì)象長(zhǎng)度獲取
當(dāng)對(duì)象包含 Symbol 屬性時(shí)呀,像 Object.keys() 和 Object.getOwnPropertyNames() 這兩個(gè)方法就存在一定的局限性啦。因?yàn)?Object.keys() 它只返回對(duì)象自身可枚舉的自有屬性的鍵組成的數(shù)組,本身就不包含 Symbol 屬性相關(guān)的內(nèi)容呢;而 Object.getOwnPropertyNames() 雖然會(huì)返回對(duì)象除了 Symbol 屬性外的所有自有屬性鍵組成的數(shù)組,也就是它也沒法把 Symbol 屬性考慮進(jìn)去統(tǒng)計(jì)對(duì)象長(zhǎng)度哦。這時(shí)候呢,就需要用到 Object.getOwnPropertySymbols() 這個(gè)方法啦。它的作用就是返回一個(gè)包含對(duì)象所有 Symbol 類型自有屬性名的數(shù)組哦。那我們?nèi)绻@取包含 Symbol 屬性在內(nèi)的對(duì)象的完整長(zhǎng)度,就可以先通過 Object.getOwnPropertyNames() 獲取普通自有屬性鍵組成的數(shù)組,再通過 Object.getOwnPropertySymbols() 獲取 Symbol 屬性名組成的數(shù)組,然后把這兩個(gè)數(shù)組的長(zhǎng)度相加,就能得到這個(gè)對(duì)象完整的屬性個(gè)數(shù),也就是對(duì)象的長(zhǎng)度啦。在這個(gè)例子中呀,對(duì)象 symbolObj 既有普通的自有屬性 normalProp ,又有 Symbol 類型的屬性 sym1 和 sym2 。通過 Object.getOwnPropertyNames(symbolObj) 得到普通屬性鍵數(shù)組長(zhǎng)度為 1,通過 Object.getOwnPropertySymbols(symbolObj) 得到 Symbol 屬性名數(shù)組長(zhǎng)度為 2,兩者相加得到總長(zhǎng)度為 3,這樣就準(zhǔn)確獲取到了包含特殊 Symbol 屬性的這個(gè)對(duì)象的完整長(zhǎng)度啦。所以呀,大家在遇到對(duì)象有 Symbol 屬性這種特殊情況時(shí),可別忘了用 Object.getOwnPropertySymbols() 這個(gè)方法來準(zhǔn)確獲取對(duì)象長(zhǎng)度哦。
四、js 對(duì)象長(zhǎng)度在實(shí)際開發(fā)中的應(yīng)用
控制對(duì)象元素?cái)?shù)量
在實(shí)際開發(fā)中呀,js 對(duì)象長(zhǎng)度的應(yīng)用場(chǎng)景可不少呢,就比如說控制對(duì)象元素?cái)?shù)量這一點(diǎn)吧。咱們可以想象一個(gè)生活中的場(chǎng)景,比如控制書包裝書本的數(shù)量。假設(shè)我們用一個(gè)對(duì)象來代表書包,對(duì)象的屬性就是每一本書那怎么知道書包里已經(jīng)裝了幾本書,也就是這個(gè)對(duì)象包含了幾個(gè)屬性呢?這時(shí)候就可以用上咱們前面講過的獲取對(duì)象長(zhǎng)度的方法啦,比如通過 Object.keys(schoolBag).length 就能得到書包里書本屬性的個(gè)數(shù),在這里返回的就是 3,代表裝了 3 本書呢。通過這樣的方式,就能很方便地基于對(duì)象長(zhǎng)度來進(jìn)行邏輯判斷,決定是否可以添加新的元素啦。其實(shí)呀,在很多類似的場(chǎng)景中,只要涉及到對(duì)對(duì)象元素?cái)?shù)量有一定限制,需要判斷是否滿足條件的情況,都可以利用獲取對(duì)象長(zhǎng)度的方法來巧妙地處理哦,大家可以聯(lián)想一下自己開發(fā)過程中遇到的類似場(chǎng)景呀。
為對(duì)象添加長(zhǎng)度屬性
除了上面說的利用現(xiàn)有方法去獲取對(duì)象長(zhǎng)度用于判斷等操作外,我們還可以主動(dòng)為對(duì)象添加長(zhǎng)度屬性哦,這在某些情況下也是很實(shí)用的呢。在 JavaScript 中,我們可以通過 Object.defineProperty 方法來為對(duì)象添加長(zhǎng)度屬性呀。通過這樣的設(shè)置,我們就給 myObject 添加了一個(gè)名為 length 的屬性啦,而且可以通過 myObject.length 來獲取它的長(zhǎng)度值,在這里就是 2 哦。不過要注意呀,為對(duì)象添加的這個(gè)長(zhǎng)度屬性并不會(huì)自動(dòng)更新哦。什么意思呢?就是說如果之后對(duì)象的屬性發(fā)生了變化,比如又新增或者刪除了某個(gè)屬性,那這個(gè)長(zhǎng)度屬性的值不會(huì)跟著自動(dòng)改變的,還是需要我們手動(dòng)去更新它的值呢所以呀,在使用為對(duì)象添加長(zhǎng)度屬性這個(gè)操作時(shí),要時(shí)刻記得它不能自動(dòng)更新這一特點(diǎn),根據(jù)實(shí)際情況適時(shí)手動(dòng)去維護(hù)長(zhǎng)度屬性的值,這樣才能保證它的準(zhǔn)確性,讓它在我們的開發(fā)中發(fā)揮出應(yīng)有的作用,比如方便地知曉對(duì)象當(dāng)前屬性的數(shù)量等情況呢。
五、總結(jié)
回顧重點(diǎn)方法
在前面的內(nèi)容中,我們?cè)敿?xì)介紹了多種獲取 JavaScript 對(duì)象長(zhǎng)度的方法呢。首先是 Object.keys() 方法,它能夠返回一個(gè)對(duì)象自身可枚舉自有屬性的鍵的數(shù)組,我們?cè)俳柚@個(gè)數(shù)組的 length 屬性,就能知曉對(duì)象的長(zhǎng)度啦,像對(duì)于 let obj = {name: 'John', age: 30, city: 'New York'}; 這樣的對(duì)象,通過 Object.keys(obj).length 就能得到其長(zhǎng)度為 3 哦。還有 for...in 循環(huán)的方式呀,利用它來遍歷對(duì)象所有的鍵,不過要配合 hasOwnProperty 方法進(jìn)行判斷,確保只統(tǒng)計(jì)對(duì)象自身的自有屬性,通過在遍歷過程中計(jì)數(shù),從而得到對(duì)象的長(zhǎng)度呢,例如特定的對(duì)象示例中可以通過這種方式準(zhǔn)確算出自有屬性的個(gè)數(shù)。Object.getOwnPropertyNames() 這個(gè)方法也不容忽視呀,它會(huì)返回包含對(duì)象所有鍵名(除了 Symbol 屬性外的所有自有屬性)的數(shù)組,接著利用該數(shù)組的 length 屬性獲取對(duì)象長(zhǎng)度,而且它和 Object.keys() 的區(qū)別在于,它除了可枚舉的自有屬性鍵之外,還會(huì)把不可枚舉的自有屬性鍵也包含進(jìn)來哦,不同場(chǎng)景下可以按需選用呢。在 ES6 相關(guān)情況里,Object.keys() 和 Object.values() 在遍歷對(duì)象時(shí)會(huì)忽略繼承屬性,讓獲取對(duì)象自身可枚舉屬性的長(zhǎng)度變得更加便捷啦。而當(dāng)對(duì)象包含 Symbol 屬性時(shí),就得用上 Object.getOwnPropertySymbols() 方法啦,它可以返回包含對(duì)象所有 Symbol 類型自有屬性名的數(shù)組,結(jié)合 Object.getOwnPropertyNames() 獲取的普通自有屬性鍵組成的數(shù)組,將二者長(zhǎng)度相加,就能得到包含 Symbol 屬性對(duì)象的完整長(zhǎng)度了哦。
強(qiáng)調(diào)適用場(chǎng)景
不同的獲取 JavaScript 對(duì)象長(zhǎng)度的方法,有著各自適合的應(yīng)用場(chǎng)景呢。如果只是想獲取對(duì)象自身可枚舉的自有屬性長(zhǎng)度,那 Object.keys() 方法就是個(gè)不錯(cuò)的選擇呀,它簡(jiǎn)潔高效,像在很多常規(guī)的對(duì)象屬性統(tǒng)計(jì)場(chǎng)景中,只要不涉及不可枚舉屬性和 Symbol 屬性的情況,用它就挺合適的。要是需要把對(duì)象除 Symbol 屬性外的所有自有屬性都統(tǒng)計(jì)進(jìn)來,包括那些不可枚舉的自有屬性,這時(shí)候 Object.getOwnPropertyNames() 方法就能派上用場(chǎng)了哦,例如在一些需要全面了解對(duì)象自有屬性個(gè)數(shù),不管其是否可枚舉的業(yè)務(wù)邏輯處理中就可以考慮使用它呢。而對(duì)于 for...in 循環(huán)獲取對(duì)象長(zhǎng)度的方式,由于它可以遍歷到對(duì)象及其原型鏈中所有可枚舉的屬性(當(dāng)然配合 hasOwnProperty 能精準(zhǔn)到自有屬性),所以在需要綜合考慮各類可枚舉屬性情況,比如排查繼承屬性干擾等場(chǎng)景下可以使用哦,不過相對(duì)來說代碼邏輯會(huì)稍微復(fù)雜一點(diǎn)啦。在 ES6 環(huán)境下,當(dāng)要處理繼承屬性并且只需關(guān)注對(duì)象自身可枚舉屬性長(zhǎng)度時(shí),Object.keys() 和 Object.values() 的便利性就體現(xiàn)出來了,能讓我們更輕松地獲取相應(yīng)長(zhǎng)度呢。最后,一旦對(duì)象包含了 Symbol 屬性,要想得到完整準(zhǔn)確的對(duì)象長(zhǎng)度,可別忘了使用 Object.getOwnPropertySymbols() 配合 Object.getOwnPropertyNames() 的方式呀,在涉及這種特殊數(shù)據(jù)類型屬性的對(duì)象長(zhǎng)度統(tǒng)計(jì)時(shí),它就是準(zhǔn)確獲取長(zhǎng)度的關(guān)鍵啦,比如在一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)或者特定的