我們知道,js的數組具有一個sort方法,這個sort方法還可以傳入一個特定形式的比較函數進行自訂排序,它的用法類似這樣:
[5,4,9,2,7].sort(function(a,b){return(a-b);});
這個特定形式的自訂比較函數,要求有兩個參數,通常情況下,函數的內容是兩個參數本身或其屬性的對比,該函數的傳回值必須為負數、0和正數之一。另外sort函數會改變數組,而不是返回一個新的數組。
最近我的一段js代碼使用了js數組的自訂排序,在ie8和ff4下正常,然而在ie6和ie7下報“缺少數字”錯誤,經過研究發現,是自訂比較函數的傳回值出現了NaN這個非數字造成的,這種情況下,ie6和ie7直接報錯,而ie8和ff4不會報錯,如下的代碼可以可以重現這個問題:
var arr = [
{o:3,toString:function(){return this.o}},
{o:undefined,toString:function(){return this.o}},
{o:4,toString:function(){return this.o}},
{o:1,toString:function(){return this.o}}
];
arr.sort(function(a,b){return a.o-b.o;});//使用元素的o屬性進行比較
debug.innerHTML=arr;
由於數組arr中有一個元素的o屬性沒有定義,因此比較函數中會出現數字與undefined相減的情況,結果就是NaN,於是ie6和ie7報錯了,如下:
解決這個問題的辦法,就是避免自訂比較函數返回非數字。但是ie8為什麼不報錯呢?難道ie8下傳給sort函數的比較函數返回NaN不抱錯嗎?答案是肯定的,當比較函數的傳回值為NaN的話,ie8不會報錯,但是排序結果會發生一些不可預料的變化,上面同樣的代碼,在ie8下的結果是:
1,3,undefined,4
這個結果令我疑惑,如果把arr改成:
var arr = [
{o:3,toString:function(){return this.o}},
{o:6,toString:function(){return this.o}},
{o:undefined,toString:function(){return this.o}},
{o:4,toString:function(){return this.o}},
{o:1,toString:function(){return this.o}}
];
則排序後結果是:
1,3,4,6,undefined
如果我把o屬性未定義的元素移到o屬性為3的元素下面,則返回結果是:
1,3,undefined,4,6
這正是我的疑惑,如果你知道答案,請不吝賜教。
那麼ie8的sort的自訂比較函數是不是無論返回什麼都不報錯呢?答案是否定的,如果我把比較函數的傳回值寫入程式碼成“return “#@#@””,則ie8也報錯了:
因此,我認為ie8的的sort函數,相比IE6和ie7,至少進行了體驗上的最佳化,即如果發現自訂比較函數的傳回值是NaN,則不報錯,只是排序可能會出現非預期的結果而已,但是如果傳回值是字串,則將嚴懲不貸,彈出令人震驚的錯誤框。