問題的發現:
我有一個接口返回一個json數據瀏覽器network里的Response里是從大到小排。
但Preview就是反過來的
問題的描述:
上面那個讓我發現瀏覽器處理對象或者json是會對其鍵值對做排序!!!
在JavaScript中,對象鍵的順序問題源于語言規范:ES6之前對象鍵序沒有明確規定,ES6之后雖然規定了自有屬性的枚舉順序,但控制臺輸出可能因瀏覽器實現而異。
您觀察到的現象是正常的:當使用console.log(data)時,瀏覽器控制臺可能會按照以下規則顯示對象:
數字鍵按數值升序排列
字符串鍵按創建順序排列
但某些瀏覽器控制臺(如Chrome)會對所有鍵進行字母排序后再顯示
問題的復現:
示例一:key是一個字符串
let obj = {"2023-08-30": "8888","2023-08-10": "5555","2023-08-08": "6666","2023-06-02": "7777","2023-06-01": "7777",};// let obj = {// "3-3": "cc",// "3-2": "bb",// "3-1": "aa",// };console.log("原數據:",obj);console.log("key數組:", Object.keys(obj));
結果分析:
1.打印出的對象和原數據不一致被正序排序了
2.使用for in或者 Object.keys時鍵值的順序沒有發生變化
示例二:key是一個數字
let obj = {20230830: "8888",20230810: "5555",20230808: "6666",20230602: "7777",20230601: "7777",};console.log("原數據:", obj);console.log("key數組:", Object.keys(obj));
結果分析:
1.打印出的對象和原數據不一致被正序排序了
2.使用for in或者 Object.keys時鍵值的順序發生變化了
示例三:key是一個字母
let obj = {c: "cc",b: "bb",a: "aa",};// let obj = {// "c": "cc",// "b": "bb",// "a": "aa",// };console.log("原數據:", obj);console.log("key數組:", Object.keys(obj));
結果分析:
1.打印出的對象和原數據不一致被正序排序了
2.使用for in或者 Object.keys時鍵值的順序沒有發生變化
總結:
經過上面的三個示例可得出:
數字字符串鍵在對象屬性遍歷時會按數值升序排列。
非數字字符串鍵按照創建順序排列。
使用Map可以完全保留插入順序。
需要注意的是JSON.parse也使用這個規則!
關鍵結論:
對象鍵序問題原因:
控制臺顯示可能對鍵進行字母排序
JavaScript規范中對象鍵的順序是:整數索引 > 字符串鍵(按創建順序)> Symbol鍵
但字符串鍵中的數字字符串會被特殊處理
特殊處理的規則如下:
具體來說,ECMAScript規范規定,對象中的數字鍵(即數字字符串鍵)會按照數值大小升序排序,而非數字字符串鍵則按照創建順序排列。
特殊處理規則:
?數字字符串鍵?:會被視為數字索引,在對象屬性遍歷時(如使用Object.keys、for…in循環等)會按照數值升序排列。
?非數字字符串鍵?:按照屬性添加到對象的先后順序排列(從ES6開始,普通對象保持字符串鍵的創建順序,但數字字符串鍵仍然會被特殊排序)。
const obj = {"100": "一百","2": "二","name": "張三","1": "一","age": 20
};console.log(Object.keys(obj));
// 輸出: [ '1', '2', '100', 'name', 'age' ]
注意:
只有看起來像非負整數的字符串(例如"123"、“0”)才會被當作數字鍵處理。像"001"、"123a"這樣的字符串不會被當作數字鍵,而是普通字符串鍵。
在ES6之前,不同JavaScript引擎對非數字字符串鍵的遍歷順序是不一致的。但從ES6開始,規范要求非數字字符串鍵按照創建順序排列,而數字字符串鍵按照數值升序排列。
是否會影響使用:
直接通過鍵訪問屬性:不受影響
遍歷對象屬性(for…in/Object.keys):順序可能不符合預期
依賴對象鍵序的業務邏輯:可能有風險
推薦解決方案:
使用Map對象保持插入順序
使用數組顯式存儲鍵的順序
在遍歷前對鍵進行排序(如按日期倒序)
還需要注意的是控制臺打印對象時可能也會出現不一致的情況,詳情可以看:js 控制臺打印對象,對象點開后里面屬性沒值,展開后有值(object展開和收起值不一致)