Может кто-нибудь объяснить эту "двойную отрицательную" трюк?

Я ни в коем случае не эксперт в 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.