標題要討論的是 { "a": 1, "b": 2 }
這樣的 object 再 JSON 與在 JavaScript 裡面有沒有定義 foreach 操作時 key 的順序。
剛剛遇到這個問題,印象中這邊有點 tricky... 找了對應的文件規範對了一下:
- JSON 定義成 unordered,所以不保證順序。
- JavaScript 在 ES2020 後有定義一組特別的順序。
JSON 的部分是出自 RFC 7159,首先是先說明 object 本身是 unordered collection:
An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.
另外在後面的描述也有提到現有 library 的現況,沒有特別提到要保持順序:
JSON parsing libraries have been observed to differ as to whether or not they make the ordering of object members visible to calling software. Implementations whose behavior does not depend on member ordering will be interoperable in the sense that they will not be affected by these differences.
JavaScript 的部分,如果看 ES2020 後比較單純,定義的順序可以在官方文件裡面「9.4.3.3 [[OwnPropertyKeys]] ( )」看到:

先吃數字的順序,再來是 property 建立的順序,最後是 symbol 建立的順序。
如果是早一點的規格,在 ES2015 (ES6) 到 ES2019 這段時間,雖然有上面的定義,但只有強制一些不常用的 function 照著這個順序實作,常見的 for-in 與 Object.keys() 都不在強制實作的範圍內;而更早的 ES5 則是類似 JSON 的定義,沒有要求順序;不過這些都偏向考古了... 現在這個年代用 JavaScript 內的 object 可以。
這邊要注意的是,JavaScript 的 JSON.parse() (從 JSON data 轉成 JavaScript data) 在遇到 object 時不保證 key 的順序,會是 library 決定要怎麼做:如果維持順序也算是 implementation side effect,不在 spec 或是 standard 的保障範圍。