6
[] == ![] // -> true.

Может кто-то объяснить как это работает

  • и ==0........ – br3t Aug 15 '17 at 21:29
  • 1
    https://habrahabr.ru/post/171359/ вроде пункт 3 про это – br3t Aug 15 '17 at 21:32
  • 1
    @br3t, хотел ту же ссылку кинуть. Вообще на ночь такие вопросы лучше не задавать, а лучше их вообще никогда не задавать. – iksuy Aug 15 '17 at 21:33
  • Ссылка на раздел спеки https://tc39.github.io/ecma262/#sec-abstract-equality-comparison – Утка Учится Укрываться Aug 15 '17 at 21:33
  • https://habrahabr.ru/company/mailru/blog/335292/#eto-fail - тут много подобных примеров – Arthur Aug 15 '17 at 21:44
  • Наоборот лучше такие вопросы задавать чтобы понять как все работает =/ Смысл того что операция == - это нестрогое сравнение которое внутри пытается стайпкастить теплое с мягким к числу.Левая часть - пустой массив - тайпкастится к 0. Правая часть - false - тоже тайпкастится к 0. – Утка Учится Укрываться Aug 15 '17 at 21:45
  • Не читайте все эти "втф javascript", почитайте спеку пройдитесь карандашиком по алгоритму и все поймете. – Утка Учится Укрываться Aug 15 '17 at 21:46
  • @УткаУчитсяУму слева тайпкастится к 0, потому что массив пустой. А справа false, потому что массив - это объект, а они всегда true. и !true равно false. но почему слева не работает все по той же логике? – Stas Tyrinov Aug 15 '17 at 22:10
  • @StasTyrinov, потому что левое выражение - объект. Правое - булевое. Объект кастится к toPrimitive, то есть в данном случае к пустой строке. А пустая строка уже в число. То есть 0. [] => "" => 0. Правая же часть после вычисления выражения ![] булевая и кастится к числу. То есть false => 0. Еще раз, слева у нас тайпкаст Object => toPrimitive (string) => toNumber. Справа вычисление выражения (в котором Object => toBoolean), и результат этого выражения toNumber. – Утка Учится Укрываться Aug 15 '17 at 22:28
  • Смысл в того что универсальную логику каста чего попало во что попало организовать не так просто как кажется. Логика по которой оно работает описана в спецификации, в разделе ссылку на который я кинул. – Утка Учится Укрываться Aug 15 '17 at 22:31
  • Ну вы и намудрили =(О.о)= –  Aug 15 '17 at 22:32
  • @УткаУчитсяУму спасибо! – Stas Tyrinov Aug 16 '17 at 02:58
  • вот здесь https://habrahabr.ru/company/mailru/blog/335292/ - что за черт , JavaScript ... – SergeyE Aug 16 '17 at 06:49

3 Answers3

6

Описание алгоритма сравнения x == y http://es5.javascript.ru/x11.html#x11.9.3

[] == ![] 

typeof([]) - object
typeof(![]) - boolean
  1. "7. Если Type(y) – Boolean, вернуть результат сравнения x == ToNumber(y)." 1.1. ToNumber(y) -> ToNumber(![]) -> ToNumber(false) (почему false смотреть тут http://es5.javascript.ru/x11.html#x11.4.9) -> 0 (почему 0 смотреть тут http://es5.javascript.ru/x9.html#x9.3)

  2. На данном этапе сравнение имеет вид x == 0 или [] == 0 и мы снова выполняем основной алгоритм сравнения: "9. Если Type(x) – Object и Type(y) –либо String, либо Number, вернуть результат сравнения ToPrimitive(x) == y."

  3. ToPrimitive(x) -> ToPrimitive([]) (правило вычисления примитивов тут http://es5.javascript.ru/x9.html#x9.1, а для объектов тут http://es5.javascript.ru/x8.html#x8.12.8):

    "Если внутренний метод [[DefaultValue]] объекта O вызывается без подсказки, он ведет себя так, как если бы подсказка была Number, кроме случаев, когда O – объект Date (см. 15.9.6), и в этой ситуации он ведет себя, как если бы подсказка была String." И так как valueOf для массива возвращает пустой массив (подсказка Number, шаги 1-2), то к нему применяется toString (подсказка Number, шаги 3-4), что вернёт в итоге пустую строку "".

  4. На данном этапе сравнение имеет вид "" == 0 и мы снова выполняем основной алгоритм сравнения: "5. Если Type(x) – String и Type(y) – Number, вернуть результат сравнения ToNumber(x) == y."
  5. ToNumber("") == 0. ToNumber("") -> 0 так как "MV StringNumericLiteral ::: [empty] равно 0." отсюда http://es5.javascript.ru/x9.html#x9.3.1.
  6. Наконец-то получем 0 == 0, что и даёт нам true.
edem
  • 5,970
4
  1. Объект всегда true, => не массив это false (логическое преобразование)
  2. Получаем сравнение разных типов => применяется численное преобразование
  3. Пустой массив преобразуется к 0, false тоже к 0
3

В JavaScript array массив представлен в виде объекта

console.log(typeof({}));
console.log(typeof([]));

Сравнивать обьекты и функции в джаваскрипте не возможно с помощью оператора сравнения

Но есть способ как это сделать с помощью JSON.stringify

 x = [1,2,3];
 y = [1,2,3];
 z = [1,2,3,4,5];

console.log(JSON.stringify(x) === JSON.stringify(y) ); console.log(JSON.stringify(x) === JSON.stringify(z) );

А также с помощью болле сложного кода на js (ссылка)

Дополнительно

Операторы сравнения в JavaScript

==  equal to
=== equal value and equal type
!=  not equal
!== not equal value or not equal type
>   greater than
<   less than
>=  greater than or equal to
<=  less than or equal to
?   ternary operator

типы данных в JavaScript