Что делает тильда, когда она предшествует выражению?

var attr = ~'input,textarea'.indexOf( target.tagName.toLowerCase() )
           ? 'value'
           : 'innerHTML'

Я видел это в ответ, и я никогда не видел его раньше.

Что это значит?

Ответ 1

~ является побитным оператором, который переворачивает все биты в его операнде.

Например, если ваш номер был 1, его двоичное представление IEEE 754 float (как JavaScript обрабатывает числа)...

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

So ~ преобразует свой операнд в 32-битное целое число (побитовые операторы в JavaScript делают это)...

0000 0000 0000 0000 0000 0000 0000 0001

Если бы это было отрицательное число, оно было бы сохранено в 2 дополнениях: инвертируйте все биты и добавьте 1.

... и затем переворачивает все его биты...

1111 1111 1111 1111 1111 1111 1111 1110

Так что же его использовать? Когда можно когда-нибудь использовать его?

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

Это также (как правило) нечеткий трюк, чтобы превратить indexOf() найденное возвращаемое значение в правду (при этом не найденное как ложное), и люди часто используют его для своего побочного эффекта усечения чисел до 32 бит (и отбрасывая его десятичное место удваивая его, фактически так же, как Math.floor() для положительных чисел).

Я говорю неясно, потому что не сразу видно, для чего он используется. Как правило, вы хотите, чтобы ваш код четко сообщал другим людям, читающим его. Хотя использование ~ может показаться классным, оно, как правило, слишком умное для своего же блага.:)

Это также менее актуально сейчас, когда JavaScript Array.prototype.includes() и String.prototype.includes(). Они возвращают логическое значение. Если ваша целевая платформа поддерживает ее, вы должны предпочесть это для тестирования на наличие значения в строке или массиве.

Ответ 2

Использование его перед выражением indexOf() эффективно дает вам правдивый/фальшивый результат вместо возвращаемого числового индекса.

Если возвращаемое значение -1, то ~-1 равно 0, потому что -1 - это строка из всех 1 бит. Любое значение, большее или равное нулю, даст ненулевой результат. Таким образом,

if (~someString.indexOf(something)) {
}

приведет к выполнению кода if, когда "something" находится в "someString". Если вы попытаетесь использовать .indexOf() в качестве логического напрямую, это не сработает, потому что иногда оно возвращает ноль (когда "что-то" находится в начале строки).

Конечно, это тоже работает:

if (someString.indexOf(something) >= 0) {
}

и это значительно менее загадочно.

Иногда вы также увидите следующее:

var i = ~~something;

Использование оператора ~ в два раза быстрее, чем это быстрый способ преобразования строки в 32-разрядное целое. Первый ~ выполняет преобразование, а второй ~ переворачивает бит обратно. Конечно, если оператор применяется к тому, что не может быть преобразовано в число, вы получаете NaN в результате. (edit — на самом деле это второй ~, который применяется сначала, но вы получаете идею.)

Ответ 3

~indexOf(item) появляется довольно часто, и ответы здесь велики, но, возможно, некоторым людям просто нужно знать, как их использовать и "пропустить" теорию:

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }

Ответ 4

~ Поименованный оператор NOT, ~x примерно такой же, как -(x+1). Это проще понять, вроде. Итак:

~2;    // -(2+1) ==> -3

Рассмотрим -(x+1). -1 может выполнить эту операцию для создания 0.

Другими словами, ~, используемый с диапазоном значений числа, приведет к значению falsy (принуждение к false от 0) только для входного значения -1, в противном случае любой другой truthy значение.

Как известно, -1 обычно называют дозорным значением. Он используется для многих функций, которые возвращают значения >= 0 для успеха и -1 для отказа в C языке. Какое же правило возвращаемого значения indexOf() в JavaScript.

Обычно проверяется наличие/отсутствие a substring в другом string таким образом

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}

Однако было бы проще сделать это через ~, как показано ниже

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}

Ответ 5

Для тех, кто рассматривает использование тильд-трюка для создания правдивого значения из результата indexOf, он более явчен и имеет меньше магии вместо этого использовать includes на String.

'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false

Обратите внимание, что это новый стандартный метод с ES 2015, поэтому он не будет работать на старых браузерах. В тех случаях, когда это имеет значение, рассмотрите возможность использования String.prototype.includes polyfill.

Эта функция также доступна для массивов с использованием того же синтаксиса:

['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false

Вот вам Array.prototype.includes polyfill, если вам нужна более старая поддержка браузера.