Відповіді:
~
є побітним оператором, який перевертає всі біти в своєму операнді.
Наприклад, якби ваш номер був 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()
виразом ефективно дає результат truthy / false, а не числовий індекс, який безпосередньо повертається.
Якщо значення повернення є -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
датується, принаймні, до 70-х років, і, мабуть, багато інших тодішніх сучасних мов програмування систем. Це, мабуть, випливає з того, як працює апаратне забезпечення; багато процесорів встановлюють нульовий біт після операції і мають відповідну інструкцію гілки для тестування.
| 0
, в цьому випадку це лише одна операція.
~~
точно так само.
~
Є побітовое НЕ Operator , ~x
приблизно такий же , як -(x+1)
. Це легше зрозуміти, начебто. Так:
~2; // -(2+1) ==> -3
Розглянемо -(x+1)
. -1
може виконати цю операцію, щоб створити 0
.
Іншими словами, ~
використання з діапазоном значень чисел призведе до помилкового (примусового до false
від 0
) значення лише для -1
вхідного значення, в іншому випадку будь-яке інше значення "truthy".
Як ми знаємо, -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, що базується на 0. Крім того, чим менше дужок, тим краще для читання
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/isissue/540
list.indexOf(item) >= 0
або ... > -1
оскільки javascript заснований на нулі і не вирішив вирішувати це з самого початку. Далі, лише думка (така ж, як у Airbnb), кожен, хто робить що-небудь значне в JavaScript, знає ++
, і хоча --
це є менш поширеним, про це можна визначити значення.
++
і --
через деякий час через примітивні методи, такі як map
і forEach
т. Д. Моя думка більше про те, чому вони також не вважали ~
надмірно складними, коли будь-який стандарт, що використовується, включає оператори збільшення та зменшення. Забороняти щось, так що CIS101 не має сенсу.
Для тих, хто розглядає можливість використання фокусу tilde, щоб створити значення " truthy" з indexOf
результату, воно більш чітке і має менше магії замість цього використовувати includes
методString
.
'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false
Зауважте, що це новий стандартний метод на ES 2015, тому він не працюватиме на старих браузерах. У випадках, коли це має значення, розгляньте можливість використання String.prototype.include polyfill .
Ця функція також доступна для масивів, що використовують той самий синтаксис :
['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false
Ось Array.prototype.includes polyfill, якщо вам потрібна підтримка старшого браузера.