Как? ~ (А не тильда/бит bang tilde) изменяют результат вызова метода "содержит/включены"?

Если вы читаете комментарии на странице jQuery inArray здесь, есть интересное объявление:

!!~jQuery.inArray(elm, arr) 

Теперь я считаю, что точка с двойным восклицанием преобразует результат в тип boolean со значением true. То, что я не понимаю, в чем заключается использование оператора тильды (~) во всем этом?

var arr = ["one", "two", "three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }

Рефакторинг инструкции if:

if (!!~jQuery.inArray("one", arr)) { alert("Found"); }

Структура:

jQuery.inArray("one", arr)     // 0
~jQuery.inArray("one", arr)    // -1 (why?)
!~jQuery.inArray("one", arr)   // false
!!~jQuery.inArray("one", arr)  // true

Я также заметил, что если я поставил тильду спереди, результат будет -2.

~!!~jQuery.inArray("one", arr) // -2

Я не понимаю цели тильды здесь. Может кто-нибудь объяснить это или указать мне на ресурс?

Ответы

Ответ 1

Оператор тильды фактически не является частью jQuery - он побитовым оператором NOT в самом JavaScript.

См . Великую тайну Тильды (~).

Вы получаете странные числа в своих экспериментах, потому что вы выполняете поразрядную логическую операцию над целым числом (которое, насколько мне известно, может храниться как два дополнения или что-то в этом роде...)

Два дополнения объясняют, как представлять число в двоичном формате. Думаю, я был прав.

Ответ 2

Там определенная причина, по которой вы иногда видите ~, применяемую перед $.inArray.

В принципе,

~$.inArray("foo", bar)

- более короткий способ сделать

$.inArray("foo", bar) !== -1

$.inArray возвращает индекс элемента в массиве, если найден первый аргумент, и возвращает -1, если его не найдено. Это означает, что если вы ищете логическое значение "это значение в массиве?", Вы не можете выполнить логическое сравнение, так как -1 является правдивым значением, а когда $.inArray возвращает 0 (значение фальшивости), это означает, что он действительно найден в первом элементе массива.

Применение побитового оператора ~ приводит к тому, что -1 становится 0 и вызывает 0, чтобы стать `-1. Таким образом, не обнаруживая значения в массиве и применяя побитовые NOT результаты в ложном значении (0), а все остальные значения возвращают не-0 чисел и будут представлять правдивый результат.

if (~$.inArray("foo", ["foo",2,3])) {
    // Will run
}

И он будет работать по назначению.

Ответ 3

!!~expr оценивает значение false когда expr - -1 противном случае - true.
Это то же самое, что и expr != -1, только сломанный *


Он работает, потому что побитовые операции JavaScript преобразуют операнды в 32-разрядные целые числа со знаком в двух дополнительных форматах. Таким образом, !!~-1 оценивается следующим образом:

   -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two complement representation of -1
  ~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
   !0 = true                                     // ! is logical not (true for falsy)
!true = false                                    // duh

Значение, отличное от -1 будет иметь как минимум один бит, равный нулю; инвертирование, это создаст правдивую ценность; применение ! оператор дважды к истинному значению возвращает boolean true.

При использовании с .indexOf() и мы хотим только проверить, является ли результат -1 или нет:

!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns  0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns  1, the expression evaluates to true

* !!~8589934591 оценивает значение false, поэтому это мерзость не могут быть надежно использованы для тестирования -1.

Ответ 4

~foo.indexOf(bar) является общим сокращением для представления foo.contains(bar), поскольку функция contains не существует.

Как правило, приведение в boolean необязательно из-за концепции JavaScript с "ложными" значениями. В этом случае он использовал для вывода функции true или false.

Ответ 5

jQuery.inArray() возвращает -1 для "not found" , дополнением которого (~) является 0. Таким образом, ~jQuery.inArray() возвращает значение falsy (0) для "not found" и правное значение (отрицательное целое число) для "найденного". !! затем формализует фальшивость/правду в вещественное булево false/true. Итак, !!~jQuery.inArray() даст true для "found" и false для "not found" .

Ответ 6

~ для всех 4 байтов int равно этой формуле -(N+1)

SO

~0   = -(0+1)   // -1
~35  = -(35+1)  // -36 
~-35 = -(-35+1) //34 

Ответ 7

Оператор ~ является оператором побитового дополнения. Integer результат из inArray() равен либо -1, когда элемент не найден, или некоторое неотрицательное целое число. Поразрядное дополнение -1 (представленное в двоичном виде как все 1 бит) равно нулю. Побитовое дополнение любого неотрицательного целого всегда отличное от нуля.

Таким образом, !!~i будет true, когда целое число "i" является неотрицательным целым числом, а false, когда "i" равно -1.

Обратите внимание, что ~ всегда зацикливает свой операнд на целое; то есть он приводит к нецелочисленным значениям с плавающей запятой в целое число, а также к нечисловым значениям.

Ответ 8

Тильда побитовое НЕ - инвертирует каждый бит значения. Как правило, если вы используете ~ для числа, его знак будет инвертирован, тогда будет вычтено 1.

Таким образом, когда вы делаете ~0, вы получаете -1 (0 инвертировано - 0, вычитание 1 равно -1).

Это по сути сложный, супер-микро-оптимизированный способ получения значения, которое всегда является логическим.

Ответ 9

Вы правы: этот код вернет false, когда вызов indexOf возвращает -1; иначе true.

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

return this.modifiedPaths.indexOf(path) !== -1;

Ответ 10

Оператор ~ является побитовым оператором NOT. Это означает, что он принимает число в двоичной форме и превращает все нули в единицы и единицы в нули.

Например, число 0 в двоичном формате равно 0000000, а -1 - 11111111. Аналогично, 1 является 00000001 в двоичном выражении, а -2 - 11111110.

Ответ 11

Моя догадка заключается в том, что он существует, потому что это несколько символов короче (авторы библиотеки всегда после этого). Он также использует операции, выполняющие только несколько машинных циклов при компиляции в собственный код (в отличие от сравнения с числом).

Я согласен с другим ответом на то, что это излишний, но, возможно, может иметь смысл в жесткой петле (требует оценки производительности, однако, в противном случае может оказаться преждевременной оптимизацией.)

Ответ 12

Я предполагаю, что это поразрядная операция, это самый быстрый (вычислительно дешевый) способ проверить, отображается ли путь в modifiedPaths.

Ответ 13

Как (~(-1)) === 0, так:

!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false