我們來看這樣壹個對象,來輸出他的屬性名稱,也就是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語句無法保證遍歷順序,應盡量避免編寫依賴對象屬性順序的代碼。如果想按照定義的次序遍歷對象屬性,請參考 這裏 針對各瀏覽器編寫特殊代碼。
由於對象的輸出是無序的,但是數組卻是有序的,所以為了保證順序,搞成數組再輸出。嗯,就是這樣!