Метод sort() сортирует элементы массива на месте и возвращает ссылку на тот же массив, теперь отсортированный. И мы также можем указать функцию сравнения, при которой применяется метод сортировки. — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Но стабильна ли функция сортировки в React Native? Давайте проверим это.

Мы говорим, что сортировка стабильна, если она сохраняет порядок элементов, которые имеют одинаковые значения для сравнения. Например, мы применяем функцию сортировки с index в качестве ключа сортировки с возрастанием к массиву, например

const list = [
  {
    name: 'name-1',
    index: 2,
  },
  {
    name: 'name-2',
    index: 0,
  },
  {
    name: 'name-3',
    index: 1,
  },
  {
    name: 'name-4',
    index: 0,
  },
  {
    name: 'name-5',
    index: 0,
  },
  {
    name: 'name-6',
    index: 0,
  },
  {
    name: 'name-7',
    index: 0,
  },
];

и получить вывод как

const list = [
  {
    name: 'name-2',
    index: 0,
  },
  {
    name: 'name-4',
    index: 0,
  },
  {
    name: 'name-5',
    index: 0,
  },
  {
    name: 'name-6',
    index: 0,
  },
  {
    name: 'name-7',
    index: 0,
  },
  {
    name: 'name-3',
    index: 1,
  },
  {
    name: 'name-1',
    index: 2,
  },
];

тогда мы говорим, что этот метод сортировки стабилен, потому что он сохраняет порядок элементов name-2, name-4, name-5, name-6, name-7, которые имеют тот же ключ сортировки, что и они.

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

А потом давайте проверим, стабильно ли это на React Native?

Мы можем создать пример проекта по инструкции (https://reactnative.dev/) или следовать руководству (https://kxie0124.medium.com/implementing-a-sticky-banner-with-animations- in-react-native-df5f619a6bb8).

И добавьте следующий код в App.tsx, прямо над оператором return

const list = [
  {
    name: 'name-1',
    index: 2,
  },
  {
    name: 'name-2',
    index: 0,
  },
  {
    name: 'name-3',
    index: 1,
  },
  {
    name: 'name-4',
    index: 0,
  },
  {
    name: 'name-5',
    index: 0,
  },
  {
    name: 'name-6',
    index: 0,
  },
  {
    name: 'name-7',
    index: 0,
  },
];

console.log(list.map(item => item.name));
const sortedList = list.sort((a, b) => a.index - b.index)
console.log(sortedList.map(item => item.name));

И тогда мы можем запустить приложение с помощью командной строки

yarn run android

or

yarn run ios

на двух платформах.

И мы должны увидеть журнал входного массива и отсортированного массива в терминале, на котором работает сервер метро, ​​например

LOG  ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"]
LOG  ["name-2", "name-4", "name-5", "name-6", "name-7", "name-3", "name-1"]

Таким образом, очевидно, что он стабилен, потому что порядок name-2, name-4, name-5, name-6, name-7 сохраняется.

Но это также сказало

Начиная с версии 10 (или EcmaScript 2019), спецификация требует, чтобы Array.prototype.sort был стабильным. До версии 10 (или EcmaScript 2019) стабильность сортировки не гарантировалась — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Но стабилен ли он на старых версиях React Native? Давайте проверим это.

Во-первых, мы можем проверить версию React Native из package.json, затем мы можем найти версию React Native этого проекта 0.69.4, последняя версия на данный момент.

Давайте создадим еще один проект с более старой версией React Native, например 0.64. Мы можем запустить следующую команду, чтобы создать проект с определенной версией React Native.

npx react-native init sorting --template [email protected]

Мы можем найти таблицу по адресу https://www.npmjs.com/package/react-native-template-typescript

А затем мы создадим приложение с той же модификацией и запустим его, мы обнаружим, что функция сортировки также стабильна.

Таким образом, мы можем сделать простой вывод, что функция сортировки стабильна с движком JS по умолчанию, потому что мы все знаем, что код JS работает на движке JS в React Native.

А как насчет другого движка JS, например Hermes. Мы все знаем, что двигатель Hermes имеет лучшую производительность, но с некоторыми затратами.

Хорошо. Включите движок Hermes как https://reactnative.dev/docs/hermes.

И снова пересоберите и запустите приложение, мы обнаружим, что оно напечатано

LOG  ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"]
LOG  ["name-4", "name-5", "name-6", "name-7", "name-2", "name-3", "name-1"]

Порядок элементов с одинаковым ключом сортировки меняется. Это не стабильная сортировка.

Так что это очевидная проблема с двигателем Hermes.

Как насчет другой версии двигателя Hermes. Но, к сожалению, версия движка Hermes связана с версией React Native как https://github.com/facebook/hermes/releases.

Поэтому нам нужно сначала обновить React Native с помощью команды

npx react-native upgrade x.xx.x

Релизные версии React Native можно найти на https://github.com/facebook/react-native/releases.

После тестирования нескольких версий мы обнаружили, что Hermes 0.11 на React Native 0.69.4 исправил эту нестабильную проблему сортировки.

Собственно, этот вопрос также рассматривается на https://github.com/facebook/hermes/issues/212.

Итак, дело закрыто.