Object.keys()是按什麼順序返回值的?
碰到了一個很有意思的問題,js中物件屬性的輸出是有序的嗎?如果有的話,那又遵循怎樣的規則呢?
這裡我們來做一個簡單的探討,工作之餘來一點趣味性的問題。雖不能醍醐灌頂,但可以鞏固所學知識,也是極好的~:see_no_evil:
一、奇怪現象
我們來看這樣一個物件,來輸出他的屬性名稱,也就是key值:
var data = {'1':'aaa','2':'bbb','3':'ccc','測試':'000'}; Object.keys(data) ; ["1", "2", "3", "測試"]
嗯,沒啥問題。那調整一下最後一項的位置,再來試試:
var data = {'測試':'000','1':'aaa','2':'bbb','3':'ccc'}; Object.keys(data); ["1", "2", "3", "測試"]
奇怪,輸出的順序被調整了,這是為什麼呢?我們繼續,換一下屬性名稱,再試一次:
var data = {'a':'000','1':'aaa','2':'bbb','3':'ccc'}; Object.keys(data); ["1", "2", "3", "a"]
依結果來看,貌似有點小規律,我們不妨猜一下。
二、大膽猜測
我們來看結果:
["1", "2", "3", "測試"] ["1", "2", "3", "a"]
會不會是按照ASC碼的大小順序來輸出的呢?
'1'<'2'<'3'<'測試' '1'<'2'<'3'<'a'
好像漏掉了一種情況(字母和漢字的屬性名稱同時存在),我們試一下:
var data = {'a':'000','3':'ccc','1':'aaa','測試':'bbb',}; Object.keys(data); ["1", "3", "a", "測試"]
調整屬性’a’和’測試’的順序呢?
var data = {'測試':'bbb','3':'ccc','a':'000','1':'aaa'}; Object.keys(data); ["1", "3", "測試", "a"]
好了,到此為止,我們可以得出結論了。
結論:物件的遍歷輸出並不是按照屬性的ASC碼升序排序的。
三、初見端倪
查閱了一些文件後,得出了以下有效結論:
1.An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value,
object, or function. A function stored in a property of an object is
called a method.
2.Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版規範。因此,使用 for-in 語句遍歷物件屬性時遍歷書序並非屬性構建順序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript
解析引擎遵循的是較老的 ECMA-262 第三版規範,屬性遍歷順序由屬性構建的順序決定。
四、真相大白
Chrome Opera 中使用 for-in 語句遍歷物件屬性時會遵循一個規律:
它們會先提取所有 key 的 parseFloat 值為非負整數的屬性,然後根據數字順序對屬性排序首先遍歷出來,然後按照物件定義的順序遍歷餘下的所有屬性。
其它瀏覽器則完全按照物件定義的順序遍歷屬性。
這和我們上面例子中的資料結果是吻合的,嗯,這就是我想要的結果!
五、結案總結
如果想順序遍歷一組資料,請使用陣列並使用 for 語句遍歷。
for-in語句無法保證遍歷順序,應儘量避免編寫依賴物件屬性順序的程式碼。如果想按照定義的次序遍歷物件屬性,請參考這裡針對各瀏覽器編寫特殊程式碼。
由於物件的輸出是無序的,但是陣列卻是有序的,所以為了保證順序,搞成陣列再輸出。嗯,就是這樣!
六、參考文件
1.ASCII參照表
http://baike.baidu.com/link?u...
2.js物件輸出順序
http://stackoverflow.com/ques...
3.遍歷出的屬性順序與物件定義時不同
http://w3help.org/zh-cn/cause...
4.控制js中的物件順序輸出
https://segmentfault.com/q/10...