Правдивые числа javascript

Исходя из этих правил:

Ложь:

  • ложный
  • 0 (ноль)
  • '' или "" (пустая строка)
  • нулевой
  • неопределенный
  • NaN (например, результат 1/0)

Правда: Все остальное

Я не могу найти правильного объяснения того, почему в следующих тестах только номер 1 оценивается как «истинный».

0 == true ("false")
1 == true ("true")
2 == true ("false")
othernumber == true ("false")

Оператор == имеет свои собственные правила преобразования различных типов, и, в частности, x == true означает, что нет означает «правдиво ли x?».

Pointy 13.09.2018 21:51
if (2 == true) console.log('nope');if (2) console.log('yes')
Eydrian 13.09.2018 21:55
"NaN (например, результат 1/0)" На самом деле результат 1/0 - Бесконечность. NaN - это то, что вы получаете, когда пытаетесь преобразовать что-либо (например, строку) в число, и это не может быть преобразовано: например, Number("foo") - это NaN.
T.J. Crowder 13.09.2018 21:56
2
3
498
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Правила «правдивости» и «ложности» применяются только тогда, когда само значение используется в качестве теста, например:

var str = "";
if (str) {
    // It's truthy
} else {
    // It's falsy
}

== имеет свой собственный, отличный набор правил для определения свободного равенства его операндов, которые подробно объясняются в спецификации Абстрактный алгоритм сравнения равенства:

  1. If Type(x) is the same as Type(y), then
    • Return the result of performing Strict Equality Comparison x === y.
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  8. If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

См. Спецификацию для получения полной информации о различных абстрактных операциях, перечисленных там, хотя названия в значительной степени говорят о том, что они делают. (Если вы посмотрите на спецификацию, вы увидите ! до ToNumber в разных местах; я удалил его выше. Это нет, логический оператор НЕ, это обозначение спецификации, относящееся к «внезапному завершению».)

Давайте проследим это для вашего примера 2 == true:

  1. Типы не совпадают, так что продолжайте
  2. x не равно null, так что продолжайте
  3. x не undefined, так что продолжайте
  4. Тип (x) действительно является числом, но тип (y) не является строкой, так что продолжайте
  5. Тип (x) не является String, так что продолжайте
  6. Тип (x) не является логическим, так что продолжайте
  7. Тип (y) является логическим, поэтому верните результат x == ToNumber (y)
    • ToNumber (true) равно 1, а поскольку 2 == 1 ложно, результат будет ложным.

Но обратите внимание, что шаг 7 отличается для вашего примера 1 == true:

  1. Тип (y) является логическим, поэтому верните результат x == ToNumber (y)
    • ToNumber (true) равен 1, а поскольку 1 == 1 истинно, результат истинен.

использование == отличается от if(something) Этот тест даст вам ожидаемые результаты:

function truthyFalsyTest()
{
    if(0) 
    {
       console.log("true");
    }
    else
    {
        console.log("false");
    }

    if(1) 
    {
       console.log("true");
    }
    else
    {
        console.log("false");
    }

    if(2) 
    {
       console.log("true");
    }
    else
    {
        console.log("false");
    }

    if(2222) 
    {
       console.log("true");
    }
    else
    {
        console.log("false");
    }
}

truthyFalsyTest();

По словам эта книга, это очень интересная причина, когда вы сравниваете что-либо с логическим значением, как вы это делаете, например, в x == y, это следует этому шаблону:

If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.

If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

Таким образом, когда вы сравниваете 1 == true, он на самом деле делает 1 == ToNumber(true), который затем превращается в 1 == 1, но когда вы делаете 2 == true, он превращается в 2 == 1, что, конечно, неверно.

Эта и некоторые другие причины, приведенные в книге, предлагают не сравнивать вещи с логическими значениями.

Когда вы проводите сравнение с логическим значением, не имеет значения, является ли само значение истинным или ложным, поскольку оно никогда не превращается в логическое значение, но логическое значение приводится к типу, который можно сравнить с другой стороной Оператор ==.

Надеюсь, вы найдете этот ответ удовлетворительным.

Дальнейший контекст: процесс называется принуждением. В Javascript значения разных типов приводятся к разным типам, пока их нельзя будет сравнить. Последний шаг в этом процессе - число.

Dylan 13.09.2018 22:04

@Dylan - Не всегда число.

T.J. Crowder 13.09.2018 22:05

Я призываю вас углубиться в эту книгу. Он показывает много темных вещей, которые происходят в JS.

Guy who types fast 13.09.2018 22:07

В JavaScript (==) - это оператор оператора равенства, в котором выполняется преобразование типа. Более строгий (===) оператор идентификации не выполняет преобразование типов.

Например, даже если число не является логическим, вы можете использовать числовое значение, где ожидается логическое значение, если используется оператор (==).

Но если вы установите более строгий оператор (===), вы увидите, что '1 === true' будет оцениваться как false.

Based on these rules: The issue here is that == does NOT operate by these rules. Whether something is truthy or not and how it behaves during equality tests are two different things. For the record a more correct test for truthyness would be

if (value) 
    return true;
else
    return false;

или даже короче - прямое преобразование Boolean(value) (и неявное преобразование !!value.

Однако во время проверки на равенство обе стороны == будут преобразованы в один и тот же базовый тип, и тогда выполняется фактическая проверка. В MDN есть список правил конвертации - прямо из него 1 == true использует число и логическое значение, поэтому базовым типом для обоих является количество. Среда JavaScript решит эту проблему, вызвав ToNumber(booleanValue), поэтому вот что на самом деле проверяет тест на равенство.

var convertedBooleanOperand = Number(true);

console.log("convertedBooleanOperand", convertedBooleanOperand);

В действительности 2 == true преобразуется в 2 == 1, который является false.

0 - это ложь, что не означает, что другое число будет истинным. Простой пример. Если вы используете === в условии, вы увидите ложь для всех чисел.

(0 == true) // false
(1 == true) // true

Работает нормально. Однако в приведенном ниже примере я не использовал оператор not (!) В условии. Итак, если условие истинно, оно должно вывести истину, иначе ложь. Тем не менее, это даст вам обратный результат.

if(0){console.log("true")}else{console.log("false")} // false
if(1){console.log("true")}else{console.log("false")} // true
if(15){console.log("true")}else{console.log("false")} // true

Теперь, если вы конвертируете числа в логические, результат будет таким, о чем вы думали.

Boolean(0) == true // false
Boolean(1) == true // true
Boolean(2) == true // true
Boolean(othernumber) == true // true

Спасибо

Я не думаю, что вопрос был в том, «как заставить этот код работать», а скорее «объяснить, почему он не работает так, как я ожидаю».

VLAZ 13.09.2018 22:11

Другие вопросы по теме