Как !! ~ (а не тильда / взрыва взрыва тильда) изменить результат вызова метода "содержит / включен" в массиве? - PullRequest
93 голосов
/ 16 февраля 2012

Если вы читаете комментарии на странице 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

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

Ответы [ 13 ]

117 голосов
/ 16 февраля 2012

Есть конкретная причина, по которой вы иногда видите ~, примененный перед $.inArray.

В основном,

~$.inArray("foo", bar)

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

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

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

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

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

И это будет работать как задумано.

102 голосов
/ 14 мая 2012

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


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

   -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's 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, будет иметь как минимум один бит равным нулю; инвертирование создаст истинную ценность; применение оператора ! дважды к истинному значению возвращает логическое значение 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 оценивается как ложное, поэтому эту мерзость нельзя надежно использовать для проверки на -1.

55 голосов
/ 16 февраля 2012

Оператор тильды вообще не является частью jQuery - это побитовый оператор НЕ в самом JavaScript.

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

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

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

32 голосов
/ 14 мая 2012

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

Обычно приведение к логическому значению не требуется из-за концепции JavaScript «ложных» значений. В этом случае используется для принудительного вывода на выходе функции true или false.

18 голосов
/ 16 февраля 2012

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

12 голосов
/ 30 января 2014

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

SO

~0   = -(0+1)   // -1
~35  = -(35+1)  // -36 
~-35 = -(-35+1) //34 
10 голосов
/ 16 февраля 2012

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

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

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

10 голосов
/ 16 февраля 2012

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

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

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

8 голосов
/ 14 мая 2012

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

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

return this.modifiedPaths.indexOf(path) !== -1;
6 голосов
/ 16 февраля 2012

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

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

...