JavaScript中的Array.prototype.sort要领详解

头几天在某公司口试的时刻被问到关于这个要领的默许值的题目(但是口试官跟我说的实际上是错的,就地我还不够底气去辩驳)。倏忽发明对这个要领的相识还不够,因而返来查了材料,看了v8引擎的完成和ECMA规范,在这分享一下我的总结。

先给几个结论把,然后我们再从ECMA规范去看这个要领。

  1. sort要领会修正底本数组。
  2. sort要领是不稳固的。
  3. sort要领能够接收一个可选的参数,comparefn(比较回调函数)。
  4. 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:

  1. If x and y are both undefined, return +0.
  2. If x is undefined, return 1.
  3. If y is undefined, return −1.
  4. If the argument comparefn was not provided in the call to sort, go to step 7.
  5. Call comparefn with arguments x and y.
  6. Return Result(5).
  7. Call ToString(x).
  8. Call ToString(y).
  9. If Result(7) < Result(8), return −1.
  10. If Result(7) > Result(8), return 1.
  11. Return +0.

以下是我简朴翻译的划定规矩:

当比较操纵函数用x,y两个参数挪用的时刻,会依据接下来的步骤举行:

  1. 假如x,y都是undefined,返回 +0
  2. 假如x是undefined,返回 1
  3. 假如y是undefined,返回 -1
  4. 假如没有供应comparefn,跳至第七步
  5. 用comparefn比较x,y
  6. 返回第五步的比较效果
  7. x.toString()
  8. y.toString()
  9. 假如第八步大于第七步,返回-1
  10. 假如第七步大于第八步,返回1
  11. 返回+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

参考材料:

  1. MDN关于sort算法的文档
  2. v8引擎数组完成
  3. ECMA-262规范
    原文作者:GDUTxxZ
    原文地址: https://segmentfault.com/a/1190000013898927
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞