解决 ES9 中 Array.prototype.sort 排序问题

阅读时长 4 分钟读完

在 ES9 中,Array.prototype.sort 方法将使用一个新的排序算法,该算法具有更好的平均性能和更好的稳定性。然而,这个新算法可能会导致某些应用程序中的不兼容性问题。本文将介绍如何解决这些问题。

常见问题

问题一:排序算法的改变

在旧的排序算法中,排序顺序与 ECMAScript 2015 (ES6) 中定义的 ToNumber 抽象操作的返回值有关。如果值不能转换为数字,则按照它们在原始数组中的相对位置进行排序。

在新的排序算法中,如果要比较的元素是对象,则会使用该对象的 toString 方法的返回值进行比较。这可能会导致不兼容性问题。例如:

问题二:稳定性的改变

在旧的算法中,如果两个元素的比较结果相同,则它们在排序后仍然按照它们在原始数组中的相对位置交换。

在新的算法中,这种情况是未定义的,也就是说,相同的元素可能变为不同顺序。例如:

解决方案

要解决这些问题,我们可以重写 sort 方法,使用一个稳定的排序算法(如归并排序),并在比较元素时,显式指定比较函数。这将确保按照我们所需的方式进行排序,并且不会受到新排序算法的影响。

以下是一个示例实现:

-- -------------------- ---- -------
-------------------------- - ------------------------- -
  ----- ------ - ------------
  ----- --- - -------------
  ----- -------- - --- --------------

  ----- ------------ - --------------- ---- -
    -- ---- - ----- - -- -
      -------
    -
    ----- ------ - ----------------- - ---- - ---
    ------------------- --------
    -------------------- -----
    ------------ ------- -----
  --

  ----- ----- - --------------- ------- ---- -
    --- - - ------
    --- - - -------
    --- - - ------

    ----- -- - ------ -- - - ---- -
      -- ------------------------ ------- -- -- -
        ------------- - ---------
      - ---- -
        ------------- - ---------
      -
    -
    ----- -- - ------- -
      ------------- - ---------
    -
    ----- -- - ---- -
      ------------- - ---------
    -
    --- ---- - - ------ - - ---- ---- -
      ------ - ------------
    -
  --

  --------------- --------
  ------ ----
--

----- --- - ------ -- ---
------------------ -- -- - - --- -- -- ----- -- -----

在此示例实现中,我们首先通过 slice() 创建一个原数组的副本以重复。然后,我们使用归并排序算法,将元素逐个合并到新数组中。最后,我们返回一个已排序的数组。

在调用 stableSort() 时,我们需要传入一个比较函数。这个函数应该与原生 sort() 方法中使用的比较函数具有相同的行为,以确保排序的正确性。

结论

在使用 ES9 中的 Array.prototype.sort 方法时,我们需要注意它的新算法可能会导致一些应用程序的不兼容性问题。然而,我们可以通过实现自己的稳定排序算法,并显式指定比较函数来解决这些问题。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6718c1acad1e889fe22e1278

纠错
反馈