Подтвердить что ты не робот

Почему (условие ==! Условие) истинно в JavaScript?

Почему именно здесь условие оценивается как true?

var condition = new Boolean(false);
if (condition == !condition)
    alert("The more you know...");
4b9b3361

Ответ 1

Разбить его:

var condition = new Boolean(false);

Это фактически объект, а condition.valueOf() === false

!{} оценивается как false, поскольку {} истинно (объяснено http://www.ecma-international.org/ecma-262/5.1/#sec-9.2)

Итак, проверка condition.valueOf() == false, которая истинна

Ответ 2

Вы сравниваете объект (LHS) с булевым false (RHS).

[object Boolean] == false

Оператор == выполняет принуждение типа в соответствии с алгоритмом сравнения абстрактного равенства, определенным ECMAScript. 11.9.3 Алгоритм сравнения абстрактного равенства

В соответствии с вашим кодом следующая точка этого алгоритма (где x - LHS, а y - RHS).

7) Если тип (y) является логическим, верните результат сравнения x == ToNumber (y).

Обратите внимание, что он сначала пытается преобразовать логическое значение в число. false boolean преобразуется в число 0, так что теперь мы имеем это:

[object Boolean] == 0

Как вы можете видеть, он рекурсивно вводит один и тот же алгоритм из-за ==. Итак, теперь мы сравниваем объект с номером, и поэтому применяется следующая точка:

9) Если тип (x) - это объект и тип (y) - это строка или номер, возвращает результат сравнения ToPrimitive (x) == y.

Итак, теперь он пытается принудить объект к его примитивному значению. От 9.1 ToPrimitive при вызове объекта:

Объект Возвращает значение по умолчанию для объекта. Значение по умолчанию для объекта извлекается, вызывая внутренний метод [[DefaultValue]] объекта, передавая необязательный подсказку PreferredType. Поведение внутреннего метода [[DefaultValue]] определяется этой спецификацией для всех собственных объектов ECMAScript в 8.12.8.

Итак, вы можете видеть, что он хочет [[DefaultValue]] объекта. Это приводит нас к 8.12.8 [[DefaultValue]], где он ожидает "подсказки". Поскольку он не получил "подсказки", он ведет себя так, как будто намек был "Number".

Когда внутренний метод [[DefaultValue]] из O вызывается без подсказки, он ведет себя так, как будто намек был Number,...

И это приводит нас к следующему поведению:

Когда вызывается внутренний метод O [[DefaultValue]] с номером подсказки, выполняются следующие шаги:

  • Пусть valueOf является результатом вызова внутреннего метода объекта [[Get]] объекта O с аргументом "valueOf".

  • Если IsCallable (valueOf) истинно, то

    а. Пусть val является результатом вызова внутреннего метода [[Call]] значенияOf, с O как это значение и пустым списком аргументов.

    б. Если val является примитивным значением, верните val.

И поэтому он вызывает метод .valueOf() объекта, доведя нас до 15.6.4.3 Boolean.prototype.valueOf()

  • Пусть B - это значение.

  • Если тип (B) является логическим, то пусть b - B.

  • Иначе, если Type (B) - это Object, а значение внутреннего свойства [[Class]] в B - "Boolean", то пусть b является значением внутреннего свойства [[PrimitiveValue]] для B.

  • Просто введите исключение TypeError.

  • Возврат b.

Итак, с шага 3 вы можете увидеть, что он вернет объект [[PrimitiveValue]] объекта. Это приводит нас к 15.6.2.1 новому булевому (значение)

Внутреннее свойство [[PrimitiveValue]] для вновь созданного булева объекта установлено в ToBoolean (значение).

Итак, вы можете увидеть, что вы, наконец, получите значение ToBoolean значения, которое вы первоначально передали конструктору, который был false. Его значение ToBoolean, очевидно, false, поэтому теперь ваше сравнение таково:

false == 0

Поскольку типы все еще не совпадают, в исходном алгоритме он перейдет к пункту 6:

6) Если тип (x) является логическим, верните результат сравнения ToNumber (x) == y.

Итак, теперь он хочет преобразовать логическое false в число. Это похоже на то, что было сделано выше. Значение false преобразуется в значение 0, поэтому теперь мы имеем:

0 == 0

И, наконец, мы сравниваем сравнение по типу, и поэтому оно ведет себя так же, как и его строгая копия ===, путем сравнения значений. И, очевидно, 0 делает равным 0, поэтому мы получаем true.


Мораль истории... это то, что вы получаете, когда задаете "почему" в JavaScript.

Ответ 3

Это действительно помогает просто прочитать спецификацию, где это логически выложено, см.

Начните с:

var x = new Boolean(false);
var y = !x;

Тогда

y = false;

Поскольку логический объект не считается булевым, но вечным объектом, ToBoolean(x) оценивается как true и !true оценивается как false

Алгоритм сравнения абстрактного равенства

Раунд 1: шаг 7

Если тип (y) булев, верните результат сравнения x == ToNumber (у).

y = 0; //ToNumber(false) is 0

Раунд 2: шаг 9

Если Type (x) - это Object и Type (y) - либо String или Number, return результат сравнения ToPrimitive (x) == y.

x = false //Basically ends up calling x.valueOf()

Раунд 3: Шаг 6

Если Type (x) является логическим, верните результат сравнения ToNumber (x) == y.

x = 0; //ToNumber(false) is 0

Наконец: Шаг 1

Если Type (x) совпадает с типом (y), то

Шаг 1 C

Если Type (x) - Number, то

Шаг 1 C iii

Если x - это то же значение числа, что и y, верните true.

Ответ 4

Одна вещь, которую я узнал из Алгоритм сравнения абстрактного равенства, забудьте интуицию и выполните следующие шаги.

Поскольку объекты правдивы, их отрицание false, поэтому в алгоритм входит следующее:

Boolean(false) == false

Если вы шаг за шагом, вы получите:

Boolean(false) == 0  // Step 7
false == 0           // Step 9
0 == 0               // Step 6
true