Может кто-нибудь объяснить эту "двойную отрицательную" трюк?
Я ни в коем случае не эксперт в Javascript, но я читал страницу Mark Pilgrim Dive into HTML5, и он упомянул что-то, что Я хотел бы лучше понять.
Он утверждает:
Наконец, вы используете двойной отрицательный трюк, чтобы заставить результат к логическому значению (true или false).
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
Если кто-нибудь может объяснить это немного лучше, я был бы признателен!
Ответы
Ответ 1
Логический оператор NOT !
преобразует значение в логическое значение, противоположное его логическому значению.
Второй !
преобразует предыдущий логический результат обратно в логическое представление его исходного логического значения.
Из этих документов для логического оператора NOT:
Возвращает false, если его единственный операнд может быть преобразован в true; в противном случае возвращает true.
Итак, если getContext
дает значение "false", !!
заставит его возвращать логическое значение false
. В противном случае он вернет true
.
Значения "falsey":
-
false
-
NaN
-
undefined
-
null
-
""
(пустая строка)
-
0
Ответ 2
Javascript имеет запутанный набор правил для того, что считается "истинным" и "ложным", когда помещается в контекст, где ожидается логическое ожидание. Но оператор логического-НЕ, !
, всегда производит правильное логическое значение (одна из констант true
и false
). Соединив два из них, идиома !!expression
создает правильную булеву с той же правдивостью, что и исходное выражение.
Зачем ты беспокоишься? Потому что он выполняет функции, подобные тем, которые вы показываете более предсказуемыми. Если в нем нет двойного отрицательного значения, он может вернуть объект undefined
, a Function
или что-то не совсем не похожее на объект Function
. Если вызывающая сторона этой функции делает что-то странное с возвращаемым значением, общий код может ошибочно ( "странно" здесь означает "что-либо, кроме операции, которая обеспечивает булевский контекст" ). Двойная отрицательная идиома предотвращает это.
Ответ 3
В javascript оператор "bang" (!) вернет true, если заданное значение истинно, 1, а не null и т.д. Оно вернет false, если значение undefined, null, 0 или пустая строка.
Таким образом, оператор bang всегда будет возвращать логическое значение, но он будет представлять противоположное значение того, с чего вы начали. Если вы снова возьмете результат этой операции и снова "bang", вы можете отменить ее снова, но все равно получите логическое значение (а не undefined, null и т.д.).
Использование бит дважды будет принимать значение, которое могло бы быть undefined, null и т.д., и сделать его просто равным false
. Это займет значение, которое могло бы быть 1, "истина" и т.д., И сделать его просто равным true
.
Код мог быть написан:
var context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;
Ответ 4
Использование переменной!! дает вам гарантию typecast для boolean.
Чтобы дать вам простой пример:
"" == false (is true)
"" === false (is false)
!!"" == false (is true)
!!"" === false (is true)
Но это не имеет смысла использовать, если вы делаете что-то вроде:
var a = ""; // or a = null; or a = undefined ...
if(!!a){
...
В случае, если он переместит его в boolean, поэтому нет необходимости делать неявный двойной отрицательный отбор.
Ответ 5
!
отбрасывает "что-то" / "все" в boolean
.
!!
возвращает исходное логическое значение назад (и гарантирует, что выражение является булевым сейчас, независимо от того, что было раньше)
Ответ 6
Первый !
принуждает переменную к булевскому типу и инвертирует ее. Второй !
снова инвертирует (дает вам исходное (правильное) логическое значение для того, что вы проверяете).
Для ясности вам лучше использовать
return Boolean(....);
Ответ 7
document.createElement('canvas').getContext
может оценивать либо undefined
, либо ссылку на объект. !undefined
дает true
, ![some_object]
дает false
. Это почти то, что нам нужно, просто перевернуто. Поэтому !!
служит для преобразования undefined
в false
и ссылки на объект true
.
Ответ 8
Это связано с слабым типом JavaScript. document.createElement('canvas').getContext
- это объект функции. Добавляя одиночный !
, он оценивает его как булевское выражение и переворачивает ответ. Добавив еще один !
, он возвращает ответ. Конечным результатом является то, что функция оценивает его как булево выражение, но возвращает фактический логический результат, а не сам объект функции. Prepending !!
- быстрый и грязный способ приведения выражения в булевский тип.
Ответ 9
Если document.createElement('canvas').getContext
не undefined
или null
, он вернет true
. В противном случае он вернет false
.