Почему или как это доказывает равенство массива 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"