Во втором случае потому, что один из аргументов имеет примитивный тип Number, объект приводится к нему же.
В первом сравниваются два объекта. При попытке привести их к числу сначала вызывается метод
valueOf()
, который для обоих возвращает не примитив (тогда бы сравнивали эти примитивы) а
this
, себя же, объект. Поэтому во вторую очередь вызывается метод
toString()
, который возвращает примитивы: пустую строку для массива и "[object Object]" для объекта.
Upd. вот статья, раскрывающая глубины:
Преобразование типов в JavaScriptотрывокВ общих чертах алгоритм выглядит следующим образом:
- Если входящее значение уже является примитивом, ничего не делать и просто вернуть его.
- Вызвать input.toString(), если результат примитив — вернуть его.
- Вызвать input.valueOf(), если результат примитив — вернуть его.
- Если ни один из методов не вернул примитив — бросить ошибку TypeError.
При численном преобразовании сначала вызывается метод valueOf(), а уже затем toString(). При строковом преобразовании наоборот — сначала происходит вызов toString(), а уже потом valueOf().
Большинство встроенных типов не имеют метода valueOf или же имеют valueOf, который возвращает свой собственный объект this, который игнорируется, так как this не является примитивом. Вот почему численное и строковое преобразование в большинстве случаев работает одинаково — оба в конечном итоге вызывают метод toString().
Мало инфы в MDNСм.
правила преобразования типов:
Когда происходит преобразование типов (т.е в случаях использования нестрогого сравнения), JavaScript преобразует типы String, Number, Boolean и Object, следующим образом:
- При сравнении числа (Number) и строки (String), JavaScript пытается преобразовать числовой литерал строки в число. Затем полученное число округляется до ближайшего возможного значения типа Number.
- Если один из операндов является логическим (Boolean), то он преобразуется в значение типа (Number). Если значение логического операнда равняется истине (true), то значение этого операнда преобразуется в 1. Иначе - в 0 (ложь / false).
- Если объект сравнивается с числом или строкой, JavaScript пытается получить значение по умолчанию для данного объекта. Полученное значение преобразуется в примитив, посредством методов valueOf() и toString(). Если преобразовать объект не удается, генерируется ошибка времени выполнения.
- Обратите внимание на то, что объект преобразуется в примитив, если, и только если, второй операнд является примитивом. В ином случае, операнды сравниваются как объекты, соответственно, операция сравнения вернет истину в том случае, если внутренние ссылки обоих объектов ссылаются на один и тот же объект в памяти.
Там же рассматривают особобый случай объекта строки
new String('foo');
по сравнению с простой строкой.