[科普] JS中Object的keys是無序的嗎

來自 「蔡昕萌」 同學的內(nèi)部分享

在最開始學習 JavaScript 時,我一直被灌輸 Object 中的 Key 是無序的,不可靠的,而與之相對的是 Map 實例會維護鍵值對的插入順序。

「But,Object 的鍵值對真的是無序的嗎?」實際上在 ES2015 以后,Object.keys 的規(guī)則變了:

在一些現(xiàn)代的瀏覽器中,keys 輸出順序是可以預(yù)測的!

Key 都為自然數(shù):

注意這里的自然數(shù)是指正整數(shù)或 0,如果是其他類的 Number —— 浮點數(shù)或者負數(shù) —— 都會走到下一組類型里,像NaN或者Infinity這種也自然歸到下一個類型里,但是像科學記數(shù)法這個會稍微特殊一點,感興趣的同學可以自己試一下。

總結(jié)來說,就是當前的 key 如果是自然數(shù)就按照自然數(shù)的大小進行升序排序。

const?objWithIndices?=?{
??23:?23,
??'1':?1,
??1000:?1000
};

console.log(Reflect.ownKeys(objWithIndices));?//?["1",?"23",?"1000"]
console.log(Object.keys(objWithIndices));?//?["1",?"23",?"1000"]
console.log(Object.getOwnPropertyNames(objWithIndices));?//?["1",?"23",?"1000"]

包括在 for-in 循環(huán)的遍歷中,keys 也是按照這個順序執(zhí)行的。

Key 都為 String:

如果 key 是不為自然數(shù)的 String(Number 也會轉(zhuǎn)為 String)處理,則按照加入的時間順序進行排序。

const?objWithStrings?=?{
??"002":?"002",
??c:?'c',
??b:?"b",
??"001":?"001",
}

console.log(Reflect.ownKeys(objWithStrings));?//?["002",?"c",?"b",?"001"]
console.log(Object.keys(objWithStrings));//?["002",?"c",?"b",?"001"]
console.log(Object.getOwnPropertyNames(objWithStrings));//?["002",?"c",?"b",?"001"]

Key 都為symbol

const?objWithSymbols?=?{
??[Symbol("first")]:?"first",
??[Symbol("second")]:?"second",
??[Symbol("last")]:?"last",
}

console.log(Reflect.ownKeys(objWithSymbols));//?[Symbol(first),?Symbol(second),?Symbol(last)]
console.log(Object.keys(objWithSymbols));//?[Symbol(first),?Symbol(second),?Symbol(last)]
console.log(Object.getOwnPropertyNames(objWithSymbols));//?[Symbol(first),?Symbol(second),?Symbol(last)]

如果 Key 都為 Symbol,順序和 String 一樣,也是按照添加的順序進行排序的。

如果是以上類型的相互結(jié)合

const?objWithStrings?=?{
??"002":?"002",
??[Symbol("first")]:?"first",
??c:?"c",
??b:?"b",
??"100":?"100",
??"001":?"001",
??[Symbol("second")]:?"second",
}

console.log(Reflect.ownKeys(objWithStrings));
//?["100",?"002",?"c",?"b",?"001",?Symbol(first),?Symbol(second)]

結(jié)果是先按照自然數(shù)升序進行排序,然后按照非數(shù)字的 String 的加入時間排序,然后按照 Symbol 的時間順序進行排序,也就是說他們會先按照上述的分類進行拆分,先按照自然數(shù)、非自然數(shù)、Symbol 的順序進行排序,然后根據(jù)上述三種類型下內(nèi)部的順序進行排序。

Recap

  1. 在 ES6 之前 Object 的鍵值對是無序的;
  2. 在 ES6 之后 Object 的鍵值對按照自然數(shù)、非自然數(shù)和 Symbol 進行排序,自然數(shù)是按照大小升序進行排序,其他兩種都是按照插入的時間順序進行排序。

References:

  • 「Property order is predictable in JavaScript objects since ES2015」: https://www.stefanjudis.com/today-i-learned/property-order-is-predictable-in-javascript-objects-since-es2015
  • 「The traversal order of object properties in ES6」: http://2ality.com/2015/10/property-traversal-order-es6.html#traversing-the-own-keys-of-an-object

喜歡的話別忘了?分享、點贊、收藏?三連~

歡迎關(guān)注公眾號?前端進階體驗?收獲更多優(yōu)質(zhì)文章~

本文使用 文章同步助手 同步

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容