Что делает тильда, когда она предшествует выражению?
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
}
~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, если вам нужна поддержка старых браузеров.