[1, 2, 4] < [1, 2, 5] //true
[1, 2, 'd'] < [1, 2, 5] //false
[1, 2, ['d', 5]] < [1, 2, [20, 5]] //false
[1, 2, 5] == [1, 2, 5] //true
[1, 2, 5] <= [1, 2, 5] //true
[1, 2, 5] >= [1, 2, 5] //true
Согласно спецификации ECMAScript 5 для выполнения операции
сравнения аргументы, которые не являются примитивами, должны быть
привидены к примитивам (если кому интересно, то пункт 11.8.5
“Алгоритм сравнения абстрактного отношения”). Сначала JavaScript
пробует преобразовать аргумент к числу с помощью метода valueOf
и только когда это не удается приводит к строковому типу (изначально
я хотел написать здесь про естественность сравнения чисел, и что
когда мы говорим, что слово А больше слова Б, то имеем в виду
длину. Но из беседы с коллегой выяснилось, что это не правда. Когда
мы сравнимаем два слова мы инстанцируем связанные с ними образы и
сравнимаем их. И только если образов не нашлось, то сравниваем слова
не как метки образов, а именно как набор букв). Для массивов метод
valueOf не определен и поэтому они сравниваются как строки:
"1,2,4" < "1,2,5" //true
"1,2,d" < "1,2,5" //false
Но все вышесказаное верно только для операций сравнения. В случае
оператора “==”” привидение к примтивам осуществляется только если
один из аргументов примитив, а во всех остальных случаях оператор
“==” возвращает true только если оба аргумента ссылаются на один
объект (пункт 11.9.3 “Алгоритм сравнения абстрактного равенства”),
что в нашем случае не так.
Следует заметить, что для объектов сравнение работать не будет,
т.к. их дефолтный toString возвращает [object Object].
Ладно, объекты сравнивать нельзя, но почему бы не проверять массивы
на равенство с помощью сравнения? Все пишут циклы, а ведь можно
обойтись одной строкой:
!(arr1 < arr2)&&!(arr1 > arr2)
Что-то подсказывает, что постоянные игры с привидением типов должны
очень сильно отъедать время и ресурсы. Сделаем небольшой
наколеночный тест:
var arr1 = [],
arr2 = [],
res,
start,
end,
len = 600000;
for(var i=0; i<len; i++){
arr1[i] = i;
arr2[i] = i;
// if(i == len-100) arr2[i] = i+1; //чтобы делать не равные массивы
}
//проверим, что массивы создались
console.log(arr1.length, arr2.length);
//наш метода
start = new Date();
res = !(arr1 < arr2)&&!(arr1 > arr2);
end = new Date();
console.log(end.getTime() - start.getTime(), res);
//классический циклический
start = new Date();
for(var i=0; i<len; i++)
res &= (arr1[i] === arr2[i]);
end = new Date();
console.log(end.getTime() - start.getTime());
Разница поражает: 123мс на 2015мс в пользу привидения типов!
Несмотря на это я не советую использовать такой метод, т.к. при
попадании в массив объектов он начнет врать, кроме того, он
использует не самое очевидное поведение языка.