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

428
58

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

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

спросил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
1
Решение
479

Там определенная причина, по которой вы иногда видите ~, применяемую перед $.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
}

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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
444

!!~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.

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
328

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

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

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

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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
253

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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
193

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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
154

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


SO


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
147

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


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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
148

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


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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
133

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


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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
117

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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
90

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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
78

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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
64

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


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

ответил(а) 2021-01-19T15:50:50+03:00 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема