Если вы читаете комментарии на inArray
странице jQuery здесь , есть интересное объявление:
!!~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
Я не понимаю, зачем здесь тильда. Может кто-нибудь объяснить это или указать мне на ресурс?
javascript
jquery
operators
bitwise-operators
user717236
источник
источник
~jQuery.inArray()
на самом деле очень полезно - возможно, даже очень хорошая причина, по которой функции поиска возвращают-1
ошибку (единственное значение, дополненное двумя значениями, является ложным). Как только вы увидели и поняли трюк, я почувствовал, что он даже более читабелен, чем!= -1
.!!~
за что .if (x != -1)
иif (~x)
для меня в том, что первое на самом деле выражает то, что вы собираетесь делать. Последнее выражает ваше желание сделать что-то совершенно другое («пожалуйста, преобразуйте мой 64-битный номер в 32-битное целое и проверьте, истинно ли побитовое НЕ этого целого числа»), где вы просто случайно получили желаемый результат в этом один случай.>= 0
вероятно , не Лит достаточно, поэтому более загадочным!!~
был использован.Ответы:
Оператор тильды на самом деле вообще не является частью jQuery - это побитовый оператор НЕ в самом JavaScript.
См . Великую Тайну Тильды (~) .
Вы получаете странные числа в своих экспериментах, потому что вы выполняете поразрядную логическую операцию с целым числом (которое, насколько я знаю, может быть сохранено как дополнение до двух или что-то в этом роде ...)
Дополнение до двух объясняет, как представить число в двоичном формате. Думаю, я был прав.
источник
Есть конкретная причина, по которой вы иногда можете увидеть
~
примененную перед$.inArray
.В принципе,
это более короткий способ сделать
$.inArray
возвращает индекс элемента в массиве, если первый аргумент найден, и возвращает -1, если он не найден. Это означает, что если вы ищете логическое значение «находится ли это значение в массиве?», Вы не можете выполнить логическое сравнение, поскольку -1 - это истинное значение, а когда $ .inArray возвращает 0 (ложное значение ), это означает, что он действительно находится в первом элементе массива.Применение
~
побитового оператора приводит-1
к тому, что становится0
, а 0 становится `-1. Таким образом, не нахождение значения в массиве и применение побитового НЕ приводит к ложному значению (0), а все остальные значения возвращают числа, отличные от 0, и будут представлять правдивый результат.И это будет работать, как задумано.
источник
!!~expr
имеет значение ,false
когдаexpr
в-1
противном случаеtrue
.Такой же
expr != -1
, только битый *Это работает, потому что побитовые операции JavaScript преобразуют операнды в 32-разрядные целые числа со знаком в формате дополнения до двух. Таким образом
!!~-1
оценивается следующим образом:Для значения, отличного от
-1
, по крайней мере, один бит будет установлен в ноль; инвертирование создаст истинное значение; применение!
оператора дважды к истинному значению возвращает логическое значение true.При использовании с
.indexOf()
и мы только хотим проверить, соответствует ли результат-1
:*
!!~8589934591
оценивается как ложь, поэтому этомерзостьне может быть надежно использован для проверки-1
.источник
~foo.indexOf(bar)
, это не означает значительной экономии символов или производительности, но это относительно распространенное сокращение, как иfoo = foo || {}
есть.!!
.>= 0
не ведет себя так же, как!!~
.!== -1
ближе.~foo.indexOf(bar)
- это обычное сокращение для обозначения,foo.contains(bar)
потому чтоcontains
функция не существует.Обычно преобразование в логическое значение не требуется из-за концепции JavaScript о «ложных» значениях. В этом случае он используется для принудительного вывода функции на
true
илиfalse
.источник
jQuery.inArray()
возвращает значение-1
«не найдено», для которого используется метод complement (~
)0
. Таким образом,~jQuery.inArray()
возвращает ложное значение (0
) для «не найдено» и истинное значение (отрицательное целое число) для «найдено».!!
затем формализует ложь / истину в реальное логическое значениеfalse
/true
. Итак,!!~jQuery.inArray()
отдамtrue
за «найдено» иfalse
за «не найдено».источник
Для
~
всех 4 байтовint
эта формула равна-(N+1)
ТАК
источник
~2147483648 != -(2147483648 + 1)
.~
Является оператором побитового дополнения. Целочисленный результатinArray()
- либо -1, если элемент не найден, либо некоторое неотрицательное целое число. Поразрядное дополнение до -1 (представленное в двоичном виде как все 1 бит) равно нулю. Поразрядное дополнение любого неотрицательного целого числа всегда не равно нулю.Таким образом,
!!~i
будет,true
когда целое число «i» является неотрицательным целым числом, аfalse
когда «i» равно -1.Обратите внимание, что
~
всегда приводит свой операнд к целому числу; то есть, он переводит нецелые значения с плавающей запятой в целые, а также нечисловые значения.источник
Тильда - это побитовое НЕ - она инвертирует каждый бит значения. Как правило, если вы используете
~
число, его знак будет инвертирован, а затем будет вычтена 1.Таким образом, когда вы это сделаете
~0
, вы получите -1 (инвертированный 0 равен -0, вычитание 1 равно -1).По сути, это тщательно продуманный, сверхмикрооптимизированный способ получения значения, которое всегда является логическим.
источник
Вы правы: этот код вернется,
false
когдаindexOf
вызов вернет -1; иначеtrue
.Как вы говорите, гораздо разумнее было бы использовать что-то вроде
источник
.js
. Сказав это, они могли бы использовать>=0
вместо!==-1
- никаких дополнительных байтов для отправки и еще более читабельны, чем версия с битовым тиддлингом.> -1
это даже более читабельно, но, вероятно, это очень субъективно.~
Оператор побитового НЕ оператор. Это означает, что он принимает число в двоичной форме и превращает все нули в единицы и единицы в нули.Например, число 0 в двоичном формате равно
0000000
, а число -111111111
. Точно так же 100000001
в двоичном формате, а -211111110
.источник
Я предполагаю, что он там, потому что он на несколько символов короче (какие авторы библиотеки всегда после). Он также использует операции, которые занимают всего несколько машинных циклов при компиляции в собственный код (в отличие от сравнения с числом).
Я согласен с другим ответом, что это излишество, но, возможно, имеет смысл в жестком цикле (однако требуется оценка прироста производительности, иначе может оказаться преждевременной оптимизацией).
источник
Я полагаю, поскольку это побитовая операция, это самый быстрый (дешевый в вычислительном отношении) способ проверить, отображается ли путь в modifiedPaths.
источник
Как
(~(-1)) === 0
, так:источник