Ответы:
~
является побитовым оператором, который переворачивает все биты в своем операнде.
Например, если бы ваш номер был 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()
«ы нашел возвращаемое значение в truthy (при принятии не нашли , как falsy ) , и люди часто используют его для его побочного эффекта усечения чисел до 32 бит (и сбросив его десятичное место, удваивая его, фактически так же, как и Math.floor()
для положительных чисел).
Я говорю неясно, потому что не сразу очевидно, для чего он используется. Как правило, вы хотите, чтобы ваш код четко передавался другим людям, читающим его. Хотя использование ~
может выглядеть круто , как правило, слишком умно для его же блага. :)
Это также менее актуально сейчас, когда JavaScript имеет Array.prototype.includes()
и String.prototype.includes()
. Они возвращают логическое значение. Если ваша целевая платформа (ы) поддерживает это, вы должны предпочесть это для проверки существования значения в строке или массиве.
value = value || default
в JavaScript это распространенная и правильная идиома, если вы знаете, когда вы можете и не можете ее использовать.
v = t ? a : b;
. Я считаю, что намного четче, чем var v; if (t} { v = a; } else { v = b; }
обычно, разбито на 5+ строк, а также яснее, чем var v = b; if (t) { v = a; }
обычно 4+ строк. Но я знаю много людей, не знакомых с ? :
операторами, которые предпочли бы второй или третий способ. Я считаю, что первый является более читабельным. Я согласен с общим принципом: сделайте код понятным, не используйте хаки. Я думаю, я просто вижу, ~v.indexOf('...')
чтобы быть очень ясным, как только я изучил это.
~
идиоматическим. технически это часть языковой спецификации , но это не такая большая часть языка в общем использовании .
Использование его перед indexOf()
выражением дает эффективный / ложный результат вместо числового индекса, который возвращается напрямую.
Если возвращаемое значение -1
, то ~-1
это 0
потому , что -1
это строка из всех 1 бит. Любое значение, большее или равное нулю, даст ненулевой результат. Таким образом,
if (~someString.indexOf(something)) {
}
вызовет выполнение if
кода, когда «что-то» находится в «someString». Если вы попытаетесь использовать .indexOf()
в качестве логического значения напрямую, это не сработает, потому что иногда он возвращает ноль (когда «что-то» находится в начале строки).
Конечно, это тоже работает:
if (someString.indexOf(something) >= 0) {
}
и это значительно менее загадочно.
Иногда вы также увидите это:
var i = ~~something;
Двойное использование этого ~
оператора - быстрый способ преобразования строки в 32-разрядное целое число. Первый ~
выполняет преобразование, а второй ~
переворачивает биты обратно. Конечно, если оператор применяется к чему-то, что не может быть преобразовано в число, вы получите NaN
в результате. ( отредактируйте - фактически это второе ~
, которое применяется первым, но вы поняли идею.)
~
при выполнении на целых числах равен -(x + 1)
.
0
бытия false
и ненулевого бытия true
восходит к далёкому прошлому , по крайней мере, к C в 70-х и, вероятно, ко многим другим тогдашним современным языкам системного программирования. Вероятно, это связано с тем, как работает оборудование; Многие процессоры устанавливают нулевой бит после операции и имеют соответствующую инструкцию перехода для ее проверки.
| 0
в этом случае это всего лишь одна операция.
~~
точно таким же образом.
~
Является побитовое НЕ Operator , ~x
примерно такой же , как -(x+1)
. Это легче понять, вроде. Так:
~2; // -(2+1) ==> -3
Посмотрим -(x+1)
. -1
может выполнить эту операцию, чтобы произвести 0
.
Другими словами, ~
использование с диапазоном числовых значений приведет к ложному (coerce to false
from 0
) значению только для -1
входного значения, в противном случае - любого другого истинного значения.
Как известно, -1
обычно это называется дозорным значением . Он используется для многих функций, которые возвращают >= 0
значения для успеха и -1
для отказа в C языке. Какое же правило возврата indexOf()
в JavaScript.
Таким образом, обычно проверяют наличие / отсутствие подстроки в другой строке.
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
}
-(x+1)
если бы увидел это в операторе if. Тильда говорит мне, что именно она делает, чтобы компенсировать ноль Javascript. Кроме того, чем меньше скобок, тем лучше для чтения
if (a.indexOf("Ba") > -1) {// found} //true
который, хотя и немного длиннее, чем примеры тильды, значительно меньше, чем два приведенных вами примера, и для новых программистов var opinion = !~-1 ? 'more' : 'less'
понятен.
~indexOf(item)
возникает довольно часто, и ответы здесь великолепны, но, возможно, некоторым людям просто нужно знать, как его использовать и «пропустить» теорию:
if (~list.indexOf(item)) {
// item in list
} else {
// item *not* in list
}
++
и --
потому, что они «поощряют чрезмерную хитрость» и все же каким-то образом ~
выжили (прячась в тени) github.com/airbnb/javascript/issues/540
list.indexOf(item) >= 0
или, ... > -1
поскольку javascript основан на нуле и не решал обратиться к этому с самого начала. Кроме того, просто мнение (то же, что и у Airbnb), любой, кто делает что-то значимое в javascript, знает ++
, и хотя это --
встречается реже, значение может быть выведено.
++
и --
через какое-то время из-за примитивных методов, таких как map
и forEach
т. Д. Я хочу больше сказать о том, почему они также не считают ~
слишком сложным, когда какой-либо используемый стандарт включает в себя операторы увеличения и уменьшения. Запрещать что-либо, чтобы CIS101 не имело никакого смысла.
Для тех, кто рассматривает возможность использования трюка тильды для создания истинного значения из 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, если вам нужна поддержка старых браузеров.