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

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

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

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

5 ответов

Решение

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

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

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

Так ~ преобразует свой операнд в 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(), Они возвращают логическое значение. Если ваша целевая платформа (ы) поддерживает это, вы должны предпочесть это для проверки существования значения в строке или массиве.

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

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

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

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

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

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

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

Иногда вы также увидите это:

var i = ~~something;

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

~ побитовый оператор НЕ, ~x примерно так же, как -(x+1), Это легче понять, вроде. Так:

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

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

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

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

Обычно проверяют наличие / отсутствие 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
}

Вы не знаете JS: Типы и грамматика Кайла Симпсона

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

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

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

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

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

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

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

Вот полифайл Array.prototype.include, если вам нужна поддержка старых браузеров.

Другие вопросы по тегам