Как же так!~ (не Тильда/банг банг Тильда) изменить результат 'содержит/в комплекте' метод выбора звонка?


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

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

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

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

13 91

13 ответов:

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

посмотреть великая тайна Тильды (~).

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

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

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

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

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


это работает, потому что JavaScript побитовые операции преобразуйте операнды в 32-разрядные целые числа со знаком в формате дополнения two. Таким образом !!~-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 принимает значение false, так что это мерзость не может быть надежно использован для проверки -1.

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

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

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

так

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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