1. 程式人生 > 程式設計 >詳解JS物件遍歷的順序問題

詳解JS物件遍歷的順序問題

可能有些同學聽過在 中遍歷物件順序不固定的這一說法。事實上,這個說法不是特別準確。

對待遍歷順序,物件有一套自己既定的規則,在此規則下呢,物件的遍歷順序會受插入元素順序的影響,但是不完全受插入元素先後順序的影響。如果您有「必須按插入元素順序遍歷」的場景,可以考慮使用 Map。
遍歷物件的方法有很多www.cppcns.com種,我們經常會使用的有 for...in ,除此之外,還有:

  • Object.keys
  • Object.entries
  • Obejct.getOwnerProPertyNames
  • Reflect.ownKeys
  • ......

上面我們列的幾個方法,都按照一樣的規則去遍歷物件。而實際的遍歷規則會根據 key 值型別的不同而不同。

在一個物件中,如果我們的 key 值是像 '1'、'200'這種正整數格式的字串。 遍歷的順序是按照 key 值的大小來排列的。
比如我們看這樣的一個例子:

const obj = {}

obj['10'] = 'a';
obj['9'] = 'b';
obj[8] = 'c';
obj[7] = 'd';

console.log(Object.keys(obj)) //  ["7","8",PZcpEqxbsb"9","10"]

我們最後的遍歷順序完全忽視了插入順序,並且,值得我們注意的是,在物件中,就算我們新增屬性時的索引值是 Number 型別,最後的結果還是會被隱式的轉為字串。

陣列作為物件的一種,也符合上面的規則,又或許,有上面的表現就是因為要相容陣列的緣故呢。除此之外,通過上面的規則,我們還可以推斷出,對類陣列(key 值是正整數且有 length 屬性)進行遍歷也是按照索引順序的。
另外,如果我們的 key 值是不能轉為正整數的字串,這其中包括了可以轉換為負數的字串( 如 '-1' )、小數格式的字串(如 '1.0' ) 和其他的字串。他們的遍歷順序會比較符合直覺,就是插入物件的順序:

const obj2 = {}

obj2['1.1'] = 'a';
obj2['1.0'] = 'b';
obj2['-1'] = 'c';
obj2['jack'] = 'd'

console.log(Object.keys(obj2)); //  ["1.1","1PZcpEqxbsb
.0","-1","jack"]

事實上,物件的索引值的型別不僅可以是字串,還可以是 Symbol 型別。對於 Symbol 型別而言,它的遍歷順序也是單純的按照插入物件的順序。

如果我們的物件綜合了上面所有的情況,客棧即一個物件的索引值出現了所有的型別(各種形式的字串、Symbol 型別),它會:

  • 先按照我們上面提的關於正整數的規則遍歷正整數部分
  • 按接下來會插入順序遍歷剩下的字串
  • 最後再按照插入順序遍歷 Symbol 型別

相信到這裡,大家已經完全明白了物件的遍歷順序問題,最後還有一點值得大家注意的點,是 for...in 的遍歷順序問題。

最開始的時候,for...in 的遍歷順序並沒有一個統一的標準,瀏覽器廠商會按照他們的喜好去設定 for...in 的遍歷順序。如果您對遍歷順序有要求並且要相容老的瀏覽器版本,建議不使用它。後來 ES 2019 的 一個提案 對此現象進行了規範,現在 for...in 的順序也遵循上面的規則。

儘管會遵循上面的規則,但是 for...in 還會遍歷原型的屬性。所以 for...in 的變數元素的規則是先按照我們上面講的物件遍歷規則去變數物件本身,接下來再按照此規則去遍歷物件的原型,以此類推,直到遍歷到頂部。

除了最後一個 for...in 的注意點之外,就沒有其他的了,其實內容比較少。

到此這篇關於詳解物件遍歷的順序問題的文章就介紹到這了,更多相關JS物件遍歷順序內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!