логическое значение в выражении if

149

Сегодня я получил замечание о коде с учетом того, как я проверяю, является ли переменная истинной или ложной в школьном задании.

Код, который я написал, был примерно таким:

var booleanValue = true;

function someFunction(){
    if(booleanValue === true){
        return "something";
    }
}

Они сказали, что лучше / аккуратнее написать так:

var booleanValue = true;

function someFunction(){
    if(booleanValue){
        return "something";
    }
}

Замечание, которое я получил по поводу части "=== true", заключалось в том, что в этом нет необходимости и может возникнуть путаница.

Однако я считаю, что лучше проверить, является ли переменная логической или нет, тем более, что Javascript - это язык со слабым типом.

Во втором примере строка также вернет «что-то»;

Итак, мой вопрос; Лучше ли потерять часть «=== true» в будущем или лучше также проверить тип переменной.

Изменить: в моем «реальном» коде логическое значение указывает, было ли удалено изображение или нет, поэтому единственные значения, которые должны иметь boolValue, - это true или false.

Например, 0 и 1 не должны быть в этой переменной.

DirkZz
источник
5
это читабельно и полезно использовать ===
Piyas De
2
+1 за === true. Избегает путаницы !!
gashu
1
@gashu Считается [0] === trueложным.
RestingRobot
1
@Jlange, не так ли? Пожалуйста, объясните
gashu
Под этим я имел в виду то, что если вы просто хотите проверить "правдивость" существования, этот оператор завершится ошибкой, даже если он должен оцениваться как истина ([0] оценивается как истина, но не без преобразования типа). Это действительно зависит от того, чего вы пытаетесь достичь с помощью своего утверждения. Используйте, === trueкогда вам нужно убедиться, что условие в точности совпадает с true.
RestingRobot

Ответы:

229

Во-первых, факты:

if (booleanValue)

Удовлетворяет ifоператору любое истинное значение, booleanValueвключая trueлюбое ненулевое число, любое непустое строковое значение, любую ссылку на объект или массив и т. Д.

С другой стороны:

if (booleanValue === true)

Это будет удовлетворять ifусловию, только если booleanValueточно равно true. Никакая другая правдивая ценность не удовлетворит его.

С другой стороны, если вы сделаете это:

if (someVar == true)

Затем Javascript будет вводить принуждение trueдля соответствия типу, someVarа затем сравнивать две переменные. Есть много ситуаций, когда это не то, что нужно. Из-за этого в большинстве случаев вы хотите избежать, ==потому что существует довольно длинный набор правил того, как Javascript будет вводить принуждение двух вещей к одному и тому же типу, и если вы не понимаете все эти правила и не можете предвидеть все, что интерпретатор JS может сделать, когда учитывая два разных типа (которые большинство разработчиков JS не могут), вы, вероятно, захотите ==полностью избежать .

В качестве примера того, насколько это может быть запутанным:

var x;

x = 0;
console.log(x == true);   // false, as expected
console.log(x == false);  // true as expected

x = 1;
console.log(x == true);   // true, as expected
console.log(x == false);  // false as expected

x = 2;
console.log(x == true);   // false, ??
console.log(x == false);  // false 

Что касается значения 2, можно подумать, что 2это правдивое значение, поэтому оно будет выгодно сравниваться с true, но это не то, как работает приведение типов. Он преобразует правое значение в соответствие с типом левого значения, поэтому оно преобразуется trueв число, 1чтобы сравнивать, 2 == 1что, конечно, не то, что вы, вероятно, планировали.

Итак, покупатель, будьте осторожны. Вероятно, лучше всего избегать ==почти во всех случаях, если вы явно не знаете типы, которые будете сравнивать, и не знаете, как работают все возможные алгоритмы приведения типов.


Итак, это действительно зависит от ожидаемых значений booleanValueи того, как вы хотите, чтобы код работал. Если вы заранее знаете, что он будет иметь только значение trueили false, то сравнивая его явно с

if (booleanValue === true)

просто лишний код и ненужный и

if (booleanValue)

компактнее и, возможно, чище / лучше.

Если, с другой стороны, вы не знаете, что booleanValueможет быть, и хотите проверить, действительно ли он установлен, и trueдругие автоматические преобразования типов не разрешены, тогда

if (booleanValue === true)

это не только хорошая идея, но и обязательная.


Например, если вы посмотрите на реализацию .on()jQuery, она имеет необязательное возвращаемое значение. Если обратный вызов вернется false, jQuery автоматически остановит распространение события. В данном конкретном случае, так как JQuery хочет распространения остановить только , если falseбыл возвращен, они проверяют возвращаемое значение для явной форме, === falseпотому что они не хотят undefinedили 0или ""или что - нибудь еще , что будет автоматически набирать конвертирование в НЕВЕРНО удовлетворять сравнение.

Например, вот код обратного вызова обработки событий jQuery:

ret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );

if ( ret !== undefined ) {
     event.result = ret;
     if ( ret === false ) {
         event.preventDefault();
         event.stopPropagation();
     }
 }

Вы можете видеть, что jQuery явно ищет ret === false.

Но есть также много других мест в коде jQuery, где уместна более простая проверка, учитывая желание кода. Например:

// The DOM ready check for Internet Explorer
function doScrollCheck() {
    if ( jQuery.isReady ) {
        return;
    }
    ...
jfriend00
источник
Я долго думал над этим вопросом, но у меня не было возможности найти кого-нибудь, чтобы спросить. Буду признателен, если вы сможете взглянуть. stackoverflow.com/questions/32615466/…
ммм
Этот ответ не совсем правильный. 'x == true' не будет истинным для ненулевых чисел.
Teemoh
@Teemoh - я не понимаю ваш комментарий. См. Jsfiddle.net/jfriend00/89h8d8tm .
jfriend00
1
Я просто хочу сказать, что «if (x)» - это не то же самое, что «if (x == true)», как вы написали в первом абзаце своего ответа. if (x) явно преобразует x в логическое представление. if (x == true) будет использовать алгоритм абстрактного сравнения EcmaScript. Вы написали, что if (x == true) будет истинным для любого ненулевого числа, непустой строки или любого объекта. Это просто неправильно. Если я запустил ваш пример с 2 вместо 1, он не сработает.
Teemoh
2
@Teemoh - я понимаю твою точку зрения. Ответ исправлен и уточнен, и я добавил раздел о приведении типов с примером, показывающим, как это может делать неожиданные вещи.
jfriend00
41

Если вы напишете:, if(x === true)Это будет верно только для x = true

Если вы напишите:, if(x)это будет верно для любого x, который не является: '' (пустая строка), false, null, undefined, 0, NaN.

Карахуна
источник
(пустая строка), false, null, undefined, 0, NaN
Oliboy50
Не забывайте NaNи -0.
haykam
8

В простом "if" переменная будет приведена к логическому типу, и для объекта будет использоваться toBoolean: -

    Argument Type   Result

    Undefined       false
    Null            false
    Boolean         The result equals the input argument (no conversion).
    Number          The result is false if the argument is +0, −0, or NaN;
                    otherwise the result is true.
    String          The result is false if the argument is the empty 
                    String (its length is zero); otherwise the result is true.
    Object          true.

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

Если вы говорите, что объект может даже не быть логическим, вам, возможно, придется учитывать не только истину / ложь.

if(x===true){
...
} else if(x===false){
....
} else {
....
}
QuentinUK
источник
5

Это зависит от вашего варианта использования. Возможно, имеет смысл проверить и тип, но если это просто флаг, это не так.

Ven
источник
При ===сравнении не выполняется приведение типов. Таким образом, код OP действительно проверяет тип флага. Успешно, только если значение является логическим и истинным.
Джесси Халлетт,
Позвольте перефразировать. Если вы знаете, что это будет правдой или ложью, это не имеет значения.
Ven
5

В общем, проще и проще опустить === true .

Однако в Javascript эти утверждения отличаются.

if (booleanValue)будет выполняться , если booleanValueэто truthy - ничего, кроме 0, false, '', NaN, null, и undefined.

if (booleanValue === true)будет выполняться только в том случае, если booleanValueточно равно true.

SLaks
источник
Это именно то, в чем я хочу быть уверен, даже когда я хочу, чтобы boolValue было истинным или ложным. Для переменной несколько раз в коде устанавливается значение true / false. Я знаю это, когда пишу код, но если я снова проверю код через год, это будет просто большим вопросительным знаком, если я не перечитаю все правильно?
DirkZz
@aldanux: Ой; Я имел в виду ''.
SLaks 06
4

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

ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Apollo
источник
Ваше последнее предложение неверно. Попробуйте ваши два утверждения if (booleanValue)и if (booleanValue==true)когда это booleanValueбудет 2. Эти два утверждения не дают одинакового результата.
jfriend00 02
Интересно. Поверю тебе на слово. Я думал в мире ObjC / C / C ++, в JS я предполагаю, что вы правы, поскольку типы данных в JS могут быть изменены, а 2 == true не будет количественно определять if then.
ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ Apollo
1
См. Мой ответ выше для этого конкретного примера. Это связано с тем, как Javascript выполняет автоматическое преобразование типов для сравнения двух значений разных типов.
jfriend00 03
3

Поскольку проверенное значение Booleanпредпочтительно использовать напрямую для меньшего количества кода, и в целом оно было таким же==true

Аляфей
источник
2

Поскольку вы уже явно инициализировали как bool, я думаю, что ===оператор не требуется.

Солнечный
источник
2

Если переменная может принимать только логические значения, разумно использовать более короткий синтаксис.

Если ему потенциально могут быть присвоены другие типы, и вам нужно отличать trueот 1или "foo", тогда вы должны использовать === true.

Barmar
источник
2

Я думаю, что ваши рассуждения верны. Но на практике я обнаружил, что гораздо чаще ===сравнение не проводится. Думаю, на то есть три причины:

  1. Обычно это не увеличивает смысл выражения - это в тех случаях, когда известно, что значение в любом случае является логическим.
  2. Поскольку в JavaScript существует большая неопределенность типа, принудительная проверка типа может укусить вас, когда вы получаете неожиданное undefinedилиnull значение значение. Часто в таких случаях вы просто хотите, чтобы ваш тест не прошел. (Хотя я пытаюсь сбалансировать эту точку зрения с девизом «быстро провалиться»).
  3. Программисты на JavaScript любят быстро играть с типами, особенно с логическими выражениями, потому что мы можем.

Рассмотрим этот пример:

var someString = getInput();
var normalized = someString && trim(someString);  
// trim() removes leading and trailing whitespace

if (normalized) {
    submitInput(normalized);
}

Думаю, такой код не редкость. Он обрабатывает случаи , когда getInput()возвращается undefined, nullили пустая строка. Из-за двух логических вычислений submitInput()вызывается только в том случае, если данный ввод представляет собой строку, содержащую непробельные символы.

В JavaScript &&возвращает свой первый аргумент, если он ложный, или второй аргумент, если первый аргумент истинен; так normalizedбудет, undefinedеслиsomeString было undefined, и так далее. Это означает, что ни один из входов в приведенные выше логические выражения на самом деле не является логическими значениями.

Я знаю, что многие программисты, которые привыкли к строгой проверке типов, съеживаются при виде такого кода. Но обратите внимание, что применение строгой типизации, вероятно, потребует явных проверок значений nullили undefined, что приведет к загромождению кода. В JavaScript это не нужно.

Джесси Халлетт
источник
1

Это зависит. Если вы обеспокоены тем, что ваша переменная может оказаться чем-то, что принимает значение ИСТИНА. Тогда необходима тщательная проверка. В противном случае решать вам. Однако я сомневаюсь, что этот синтаксис whatever == TRUEкогда-либо запутает кого-либо, кто знает, что делает.

Usumoio
источник
1

В Javascript идея логического значения довольно неоднозначна. Учти это:

 var bool = 0 
 if(bool){..} //evaluates to false

 if(//uninitialized var) //evaluates to false

Поэтому, когда вы используете оператор if (или любой другой оператор управления), необязательно использовать «логический» тип var. Поэтому, на мой взгляд, часть вашего утверждения "=== true" не нужна, если вы знаете, что это логическое значение, но абсолютно необходима, если ваше значение является неоднозначным "истинным" var. Подробнее о логических значениях в javscript можно найти здесь .

ОтдыхающийРобот
источник
1

Также может быть протестирован с помощью логического объекта, если вам нужно протестировать объект error={Boolean(errors.email)}

Игорь Павленко
источник