Как говорится в заголовке, почему:
> !!1=="1"
равно
True
и
> !!2=="2"
равны:
False
Аналогично, почему > "1"==true
равно true
и > "2"==true
равно false
Я озадачен. Это просто ошибки в JS или что здесь происходит?
Как говорится в заголовке, почему:
> !!1=="1"
равно
True
и
> !!2=="2"
равны:
False
Аналогично, почему > "1"==true
равно true
и > "2"==true
равно false
Я озадачен. Это просто ошибки в JS или что здесь происходит?
В соответствии с правилами приоритета оператора логический !
имеет более высокий приоритет над ==
. Итак, в обоих случаях сначала оценивается !!
.
Примечание: Правка различных объектов объясняется в этом ответе.
!!1 == "1"
!1
будет оцениваться до false
, так как 1
считается Truthy. Отрицая снова, получим true
. Таким образом, выражение становится
true == "1"
Теперь применяются правила принуждения, так как вы использовали оператор ==
, который оценивается как Алгоритм сравнения абстрактного равенства в спецификации ECMAScript 5.1,
6. Если
Type(x)
-Boolean
, верните результат сравненияToNumber(x) == y
.
Итак, true
будет преобразован в число, равное 1 согласно ToNumber
алгоритм для логических значений. Теперь выражение становится
1 == "1"
Теперь
4. Если
Type(x)
Number
иType(y)
-String
, верните результат сравненияx == ToNumber(y)
.
Итак, "1"
будет преобразован в число, и это даст 1, согласно алгоритму ToNumber
. Вот почему он показывает true
в первом случае.
Здесь применяются те же правила.
!!2 == "2"
становится
true == "2"
затем
1 == "2"
который становится
1 == 2
который не является true
, поэтому второй случай печатает false
.
TL;DR; это связано с [ToNumber] конверсиями в алгоритме оператора ==
.
Первый шаг - упростить выражение. Поскольку !!x=="x"
анализируется как (!!x)=="x"
и !!a_truthy_expression -> true
, фактическое релевантное выражение для равенства равно
!!1=="2" -> true=="1" -> Boolean==String
!!2=="2" -> true=="2" -> Boolean==String
Итак, посмотрим на правила для 11.9.3 Алгоритм сравнения абстрактного равенства и далее вместе с приложением дает
Правило 6 - Если тип (x) булев, верните результат сравнения ToNumber (x) == y.
что приводит к Number==String
или 1 == "1" и 1 == "2", соответственно 1. Тогда правило
Правило 7 - Если Type (x) - Number и Type (y) - String, верните результат сравнения x == ToNumber (y).
что приводит к Number==Number
или 1 == 1 и 1 == 2, соответственно 1; последнее явно ложно.
Правило 1. Если тип (x) совпадает с типом (y), то [по c.iii.] Если x - это то же числовое значение, что и y, верните true [else return false].
(Тот же алгоритм объясняет случай String==Boolean
, когда применяются дополнительные правила.)
1 Чтобы увидеть правило [ToNumber], используйте:
+false -> 0
+true -> 1
+"1" -> 1
+"2" -> 2
Его проблема с приоритетом оператора.
Оператор !
является унарным оператором. Это означает, что левая сторона должна быть выражением или логическим анализируемым разделом. См. Javascript MDN.
!!1==1 is not necessary !!(1==1)
!!2==2 is not necessary !!(2==2)
Я думаю, что эти выражения должны быть последовательными, если равный оператор имеет больше приоритетов, чем! оператор. Но если мы рассмотрим обратное, оценивая первые отрицания, имеем:
!!1 == 1
!1 -> false
!!1 -> true
!!1 == 1
И с двумя
!!2==2
!2 -> false
!!2 -> true
(!!2) == 2 -> false
Это потому, что! оператор имеет приоритет над == operator
!!1
равно true, а "1" равно true ( "0" - false, так же как и любая другая строка). Итак, !!1 == "1"
оценивается как true == true
, который, конечно, возвращает true.
!!2
также равно true. Как я упоминал ранее, "2" не "1", поэтому он неверен. Поэтому мы имеем true == false
, который, конечно, возвращает false.
Если вы хотите увидеть, является ли 2 (число) равным "2" (строковое представление числа), тогда все, что вам нужно сделать, это 2 == "2"
, который оценивается как 2 == 2
, что верно, Разница в том, что мы не сравниваем логическое значение с логическим. Мы сравниваем число против числа.
В принципе, размещение !!
перед числом преобразуется в логическое, что заставляет JavaScript отличать вашу строку от булева, а не от числа.
Потому что "1" можно считать "истинным", когда вы выполняете проверку равенства, а не идентификатор, но "2" - не можете.