Відповіді:
~є побітним оператором, який перевертає всі біти в своєму операнді.
Наприклад, якби ваш номер був 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, якщо вам потрібна підтримка старшого браузера.