Вопрос по javascript, jquery – Как !! ~ (а не тильда / взрыва взрыва тильда) изменить результат вызова метода "содержит / включен" в массиве?

93

Если вы читаете комментарии в JQueryinArray страницаВотесть интересная декларация:

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

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

@ Амадан - нет. Просто нет. Серьезно, я не могу поверить, что ты защищаешь!!~ заanything. Kirk Woll
>= 0 вероятно, не былоleet достаточно, так что более загадочный!!~ использовался. Yoshi
Кто бы ни писал такой код, он должен отойти от клавиатуры. Kirk Woll
@KirkWoll: почему?~jQuery.inArray() на самом деле очень полезно - возможно, даже очень веская причина, почему функции поиска возвращают-1 для неудачи (единственное значение, чьи два дополнения являются ложными). После того, как вы увидели и поняли трюк, я чувствую, что он даже более читабелен, чем!= -1. Amadan
Проблема в том, что это просто «хитрость». Основное различие междуif (x != -1) а такжеif (~x) для меня это то, что первое действительно выражает то, что вы намерены делать. В последнем выражается, что вы хотите сделать что-то еще целиком («пожалуйста, преобразуйте мое 64-разрядное число в 32-разрядное целое число и проверьте, является ли поразрядное НЕ этого целого числа правдивым»), где вы случайно получите желаемый результат в это один случай. JimmiTh

Ваш Ответ

13   ответов
3

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

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

102

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

Error: User Rate Limit Exceededwho can read codeError: User Rate Limit Exceededwouldn't even be able to use !!.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded~foo.indexOf(bar)Error: User Rate Limit Exceededfoo = foo || {} является.
Строго говоря,>= 0Error: User Rate Limit Exceeded!!~. !== -1Error: User Rate Limit Exceeded
1

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

!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false
Я думаю, что этот ответ имеет смысл. Если у вас математический мозг, вы можете четко видеть, какие части меняются на каждом этапе. ЭтоbestError: User Rate Limit Exceeded
Это может быть точным, но это полезное объяснение для спрашивающего? Не за что. Если бы я не понял этого с самого начала, такой краткий ответ не помог бы.
8

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

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

return this.modifiedPaths.indexOf(path) !== -1;
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededonceError: User Rate Limit Exceeded.js, Сказав это, они могли бы использовать>=0 скорее, чем!==-1Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded> -1Error: User Rate Limit Exceeded
18

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

55

побитовым оператором НЕ в самом JavaScript.

УвидетьВеликая Тайна Тильды (~).

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

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
117

~ применяется перед$.inArray.

В принципе,

~$.inArray("foo", bar)

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

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

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

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

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

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

Насколько хорошо это поддерживается в браузерах (сейчас в 2014 году?) Или оно было поддержано идеально все время?
Error: User Rate Limit Exceeded
10

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

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

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

10

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

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

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

12

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

SO

~0   = -(0+1)   // -1
~35  = -(35+1)  // -36 
~-35 = -(-35+1) //34 
Это не всегда так, поскольку (например)~2147483648 != -(2147483648 + 1).
6

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

Например, число 0 в двоичном виде0000000в то время как -111111111, Аналогично, 100000001 в двоичном виде, а -211111110.

2

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

32

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

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

+1 Этот ответ объясняет «почему» лучше принятого ответа.
Хорошее объяснение~foo.indexOf(bar), Спасибо!

Похожие вопросы