Почему или как это доказывает равенство массива JavaScript?

В этом ответе есть простая функция, которая вернет равенство массива для массивов, содержащих примитивные значения.

Однако я не уверен, почему он работает. Вот функция:

function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }

Меня больше всего интересует вторая половина; этот бит:

!(a<b || b<a)

Почему работают < и > при сравнении массивов, но == нет?

Как работают методы JavaScript и меньше, чем методы?

Ответ 1

С </> массивы сначала преобразуются в строки и, как таковые, не обеспечивают надежный метод проверки равенства.

== не работает, потому что объекты проверяются по ссылке:

[] == []; // false, two separate objects

var a = [];
a == a; // true, refer to the same object

Тройка </> ошибочна:

var a = [1, [2, 3]],
    b = [[1, 2], 3];

!(a<b || b<a); // true

Это оценивается как true, потому что они оба преобразуются в строку "1,2,3", прежде чем они будут проверены (</> не работают непосредственно для объектов).

Итак, в основном вы сравниваете равенство строк. Для строк a == b действительно совпадает с !(a<b || b<a) - </> для строк кода символов символов, поэтому две равные строки не являются ни "меньшими", ни "большими", потому что это не так для любого символьного кода в строках.

Ответ 2

Однако я не уверен, почему он работает.

Это не работает. Рассмотрим

arrays_equal(["1,2"], [1,2])

производит истинное значение, хотя при любом определении равенства массива, основанном на сравнении по элементам, они различны.

arrays_equal([[]], [])

и

arrays_equal([""], [])

также являются ложными позитивами.

Простое добавление проверки length не поможет, как продемонстрировано

arrays_equal(["1,2",3], [1,"2,3"])

arrays_equal(
    ["",","],
    [",",""])

EDIT:

Если вам нужен лаконичный способ проверить структурное сходство, я предлагаю:

function structurallyEquivalent(a, b) {
  return JSON.stringify(a) === JSON.stringify(b);
}

Это не останавливается на ранних входах, которые явно отличаются друг от друга - он просматривает оба графических объекта независимо от того, насколько они не похожи, но также и функция в OP.

Одно предупреждение: когда вы используете не-native JSON.stringify, он может делать странные вещи для циклических входов, например:

var input = [];
input[0] = input;

Ответ 3

Вы можете сравнить любые два объекта с помощью ==. Но так как & для объектов не определены, они преобразуются в строки. Поэтому [1,2,3]>[2,1,3] фактически выполняет "1,2,3">"2,1,3"