66

Как понимать двойное отрицание: !! (например, в JavaScript)?

Nick Volynkin
  • 34,094
dfhsfhgfj
  • 2,274

1 Answers1

114

В javascript всякое значение может быть интерпретировано как Boolean. (Правила этой интерпретации довольно сложны и не вполне интуитивны.)

Если вы укажете какое-нибудь выражение там, где ожидается Boolean (например, внутри if'а), оно проинтерпретируется как Boolean, и всё. Но если вы хотите получить соответствующий Boolean (например, чтобы вернуть его из функции или присвоить другой переменной), вам нужен трюк, который заставит систему проинтерпретировать ваше выражение в булевом контексте.

Для этой цели традиционно используется двойное отрицание: первое отрицание "требует" булев контекст, так что выражение интерпретируется как Boolean, а второе отрицание "отменяет" первое.

Из документации:

Оператор отрицания: возвращает false если его аргумент может быть преобразован в true, в противном случае возвращает true.


Для справки: значения, которые в булевом контексте будут проинтерпретированы как false суть следующие:

  • число 0.0
  • число NaN
  • undefined
  • null
  • пустая строка
  • ну и конечно false

Все остальные значения будут проинтерпретированы как true.

Пример: если x -- объект или null, вместо

if (x != null)
    return true;
else
    return false;

можно воспользоваться изящным

return !!x;

По поводу других языков: подобный трюк нужен в основном в слабо типизированных языках вроде javascript'а, в котором значением переменной может быть и true/false, и undefined, и функция, и объект. Применение двойного отрицания гарантирует отсутствие неожиданностей в поведении полученного объекта: его тип то уж точно boolean. Однако, я встречал этот трюк и в C++ в контексте явного преобразования указателя в bool.

VladD
  • 206,799
  • 12
    хороший пример эталонного ответа – Spectre Feb 01 '13 at 06:37
  • 1
    Это дает какой-либо выигрыш по сравнению с return Boolean(x) или они абсолютно равноценны? – mirus Feb 01 '13 at 10:41
  • 5
    @mirus: насколько я понимаю, Boolean(x) то же что и !!x. Stackoverflow подсказывает, что также +x -- то же, что и Number(x). (Автор ответа считает такие паттерны хаком.) Заметьте, что new Boolean(x) -- не то же самое:
    typeof(!!x) === "boolean"
    typeof(Boolean(x)) === "boolean"
    typeof(new Boolean(x)) === "object"
    
    – VladD Feb 01 '13 at 11:09
  • 3
    да с new Boolean ваще есть прикол, это объект и получаем что new Boolean(false) если проверить в условие вернет true т.е var v = new Boolean(false); if(v) alert('во как'); – Ильяс Feb 06 '13 at 05:35
  • 2
    @ilyas: Так и есть: тип new Boolean(false) -- объект, он будет интерпретироваться как false только если null. А вот тип Boolean(false) -- boolean. – VladD Feb 06 '13 at 16:01