头几天在某公司口试的时刻被问到关于这个要领的默许值的题目(但是口试官跟我说的实际上是错的,就地我还不够底气去辩驳)。倏忽发明对这个要领的相识还不够,因而返来查了材料,看了v8引擎的完成和ECMA规范,在这分享一下我的总结。
先给几个结论把,然后我们再从ECMA规范去看这个要领。
- sort要领会修正底本数组。
- sort要领是不稳固的。
- sort要领能够接收一个可选的参数,comparefn(比较回调函数)。
- sort要领始终是默许升序的。
1.sort要领会修正底本数组
let a = [1, 20, 13, 110]
a.sort()
console.log(a) // 输出[1, 110, 13, 20]
如上,a在挪用sort要领后,本身数组被修正。
2.sort要领是不稳固的
这句话详细来说应该是,sort要领在长数组排序的时刻是不稳固的。在v8引擎的里,关于短数组会运用插入排序,而插入排序是稳固的。关于长数组会运用疾速排序,而疾速排序平常是不稳固的。详细能够读v8引擎的代码,v8引擎内的数组要领完成,从710行最先。
3.sort要领能够接收一个可选的参数,ccomparefn(比较回调函数)。
我们来看一下v8引擎中关于这一部份的代码
if (!IS_CALLABLE(comparefn)) { comparefn = function (x, y) { if (x === y) return 0; if (%_IsSmi(x) && %_IsSmi(y)) { return %SmiLexicographicCompare(x, y); } x = TO_STRING(x); y = TO_STRING(y); if (x == y) return 0; else return x < y ? -1 : 1; }; }
能够看出,在不通报comparefn这个参数的情况下,默许会运用转换为的字符串的诸个字符的Unicode位点举行排序。别的值得注意的一点是,undefined在默许情况下老是会被排在数组的末了,这一点能够参考ECMA-262规范中关于Array.prototype.sort(comparefn)的形貌。
When the SortCompare operatoris called with two arguments x and y, the
following steps are taken:
- If x and y are both undefined, return +0.
- If x is undefined, return 1.
- If y is undefined, return −1.
- If the argument comparefn was not provided in the call to sort, go to step 7.
- Call comparefn with arguments x and y.
- Return Result(5).
- Call ToString(x).
- Call ToString(y).
- If Result(7) < Result(8), return −1.
- If Result(7) > Result(8), return 1.
- Return +0.
以下是我简朴翻译的划定规矩:
当比较操纵函数用x,y两个参数挪用的时刻,会依据接下来的步骤举行:
- 假如x,y都是undefined,返回 +0
- 假如x是undefined,返回 1
- 假如y是undefined,返回 -1
- 假如没有供应comparefn,跳至第七步
- 用comparefn比较x,y
- 返回第五步的比较效果
- x.toString()
- y.toString()
- 假如第八步大于第七步,返回-1
- 假如第七步大于第八步,返回1
- 返回+0
因而[1, 20, 2, 10].sort()的效果会是[1, 10, 2, 20],而不是预期的[1, 2, 10, 20]。
4. sort要领始终是默许升序的。
别的关于怎样依据x,y比较效果举行排序,有以下划定规矩:
- 假如 comparefn(a, b) 小于 0 ,那末 a 会被排列到 b 之前;
- 假如 comparefn(a, b) 即是 0 , a 和 b 的相对位置稳定。备注: ECMAScript 规范并不保证这一行动,而且也不是一切浏览器都邑恪守(比方 Mozilla 在 2003 年之前的版本, 比方v8引擎, 这一点实在就是上面所说的排序不稳固);
- 假如 comparefn(a, b) 大于 0 , b 会被排列到 a 之前。
所以sort要领返回的数组永远是该要领以为的升序数组。我们要做的事变就是令我们想要放在背面的数大于放在前面的数。
比方我们想要返回一个降序的数字数组传入的comparefn应该是 (a, b) => b - a
参考材料: