JavaScript (ECMAScript) | Array.prototype.sort(comparefn) | 17 декабря 2021

JavaScript (ECMAScript) | Array.prototype.sort(comparefn) | 17 декабря 2021

Элементы этого массива отсортированы. Сортировка должна быть стабильной (то есть элементы, которые сравнивают равные, должны оставаться в исходном порядке). Если comparefn не является undefined, это должна быть функция, которая принимает два аргумента x и y и возвращает отрицательное Число (Number), если x < y, положительное Число (Number), если x > y, или ноль в противном случае.

 

При вызове метода сортировки sort выполняются следующие шаги:

1. Если comparefn не является undefined, а IsCallable(comparefn) имеет значение false, генерировать исключение TypeError.
2. Пусть obj будет ? ToObject(значение this).
3. Пусть len будет ? LengthOfArrayLike(obj).
4. Пусть items будет новым пустым Списком.
5. Пусть k равно 0.
6. Повторить, пока k < len,
  а. Пусть Pk будет ! ToString(𝔽(k)).
  b. Пусть kPresent будет? HasProperty(obj, Pk).
  c. Если kPresent является true (истинно), то
    i. Пусть kValue будет? Get(obj, Pk).
    ii. Добавить kValue к items.
  d. Установите k на k + 1.
7. Пусть itemCount будет количеством элементов в items.
8. Сортировка элементов items с помощью определенной реализацией последовательности вызовов SortCompare. Если какой-либо такой вызов возвращает внезапное завершение, остановитесь перед выполнением любых дальнейших вызовов SortCompare или шагов в этом алгоритме и верните это завершение.
9. Пусть j равно 0.
10. Повторите, пока j < itemCount,
  а. Выполнять ? Set(obj, !ToString(𝔽(j)), items[j], true).
  b. Установите j на j + 1.
11. Повторите, пока j < len,
  а. Выполнять ? DeletePropertyOrThrow(obj, !ToString(𝔽(j))).
  b. Установите j на j + 1.
12. Вернуть obj.

 

Порядок сортировки (sort order) — это упорядочение после завершения этой функции значений свойств с целочисленным индексом объекта obj, чьи целочисленные индексы меньше len. Затем результат функции сортировки sort определяется следующим образом:

Порядок сортировки определяется реализацией, если выполняется одно из следующих условий:

  • Если comparefn не является undefined и не является последовательной функцией сравнения для элементов items (смотри ниже).
  • Если comparefn является undefined и SortCompare не действует как функция согласованного сравнения.
  • Если comparefn является undefined, и все приложения ToString для любого конкретного значения, переданного в качестве аргумента в SortCompare, не приводят к одинаковому результату.

Если порядок сортировки не указан выше как определяемый реализацией, элементы items должны удовлетворять всем следующим условиям после выполнения шага 8 алгоритма, приведенного выше:

  • Должна существовать некоторая математическая перестановка π неотрицательных целых чисел, меньших itemCount, такая, что для каждого неотрицательного целого числа j, меньшего, чем itemCount, элемент old[j] точно такой же, как new[π(j)].
  • Тогда для всех неотрицательных целых чисел j и k, каждое из которых меньше itemCount, если SortCompare(old[j], old[k]) < 0 (смотри SortCompare ниже), то π(j) < π(k).

Здесь обозначение old[j] используется для ссылки на items[j] перед выполнением шага 8, а обозначение new[j] — для ссылки на items[j] после того, как шаг 8 был выполнен.

Функция comparefn является последовательной функцией сравнения для набора значений S, если все перечисленные ниже требования выполняются для всех значений a, b и c (возможно, одного и того же значения) в наборе S: Обозначение a < CF b означает comparefn(a, b) < 0; a = CF b означает comparefn(a, b) = 0 (любого знака); и a > CF b означает comparefn(a, b) > 0.

  • Вызов comparefn(a, b) всегда возвращает одно и то же значение v, если задана конкретная пара значений a и b в качестве двух его аргументов. Кроме того, Type(v) — это Number, а v — не NaN. Обратите внимание, что это означает, что ровно одно из a < CF b, a = CF b и a > CF b будет истинным для данной пары a и b.
  • Вызов comparefn(a, b) не изменяет obj или какой-либо объект в цепочке прототипов obj.
  • a = CF a (рефлексивность)
  • Если a = CF b, то b = CF a (симметрия)
  • Если a = CF b и b = CF c, то a = CF c (транзитивность =CF)
  • Если a < CF b и b < CF c, то a < CF c (транзитивность <CF)
  • Если a > CF b и b > CF c, то a > CF c (транзитивность >CF)
Примечание 1

Вышеупомянутые условия необходимы и достаточны, чтобы гарантировать, что comparefn разбивает множество S на классы эквивалентности и что эти классы эквивалентности полностью упорядочены.

Примечание 2

Функция сортировки намеренно универсальна; это не требует, чтобы это значение было массивом. Следовательно, его можно передать другим видам объектов для использования в качестве метода.

 

SortCompare ( x, y )

Абстрактная операция SortCompare принимает аргументы x и y. Она также имеет доступ к аргументу comparefn, переданному текущему вызову метода сортировки sort. При вызове она выполняет следующие шаги:

1. Если x и y оба не определены (undefined), верните +0𝔽.
2. Если x не определен (undefined), верните 1𝔽.
3. Если y не определено (undefined), вернуть -1𝔽.
4. Если comparefn не undefined, тогда
   a. Пусть v будет ? ToNumber(? Call(comparefn, undefined, «x, y»)).
   b. Если v равно NaN, вернуть +0𝔽.
   c. Вернуть v
5. Пусть xString будет? ToString(х).
6. Пусть yString будет? ToString(y).
7. Пусть xSmaller будет результатом выполнения абстрактного реляционного сравнения xString < yString.
8. Если xSmaller истинно true, вернуть -1𝔽.
9. Пусть ySmaller будет результатом выполнения абстрактного реляционного сравнения yString < xString.
10. Если ySmaller истинно true, верните 1𝔽.
11. Вернуть +0𝔽

Примечание 1

Поскольку несуществующие значения свойств всегда сравниваются больше, чем undefined значения свойств, а undefined всегда сравнивает большее, чем любое другое значение, значения undefined свойств всегда сортируются до конца результата, за которым следуют несуществующие значения свойств.

Примечание 2

Вызов методов, выполняемых абстрактными операциями ToString на шагах 5 и 6, может привести к тому, что SortCompare не будет вести себя как функция согласованного сравнения.

 

Информационные ссылки

Стандарт ECMAScript — Раздел «23.1.3.28 Array.prototype.sort ( comparefn )» — https://tc39.es/ecma262/#sec-array.prototype.sort