Odpowiedzi:
~
jest bitowym operatorem, który odwraca wszystkie bity w swoim operandzie.
Na przykład, jeśli twój numer to 1
, jego binarna reprezentacja liczby zmiennoprzecinkowej IEEE 754 (jak JavaScript traktuje liczby) byłaby ...
0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
~
Konwertuje więc operand na 32-bitową liczbę całkowitą (robią to operatory bitowe w JavaScript) ...
0000 0000 0000 0000 0000 0000 0000 0001
Gdyby była liczbą ujemną, byłaby zapisana w uzupełnieniu 2: odwróć wszystkie bity i dodaj 1.
... a następnie odwraca wszystkie swoje części ...
1111 1111 1111 1111 1111 1111 1111 1110
Więc po co z tego pożytek? Kiedy można go kiedykolwiek użyć?
Ma kilka zastosowań. Jeśli piszesz rzeczy niskiego poziomu, jest to przydatne. Jeśli profilowałeś swoją aplikację i znalazłeś wąskie gardło, możesz zwiększyć jej wydajność, stosując bitowe sztuczki (jako jedno z możliwych narzędzi w znacznie większej torbie).
Jest to także (ogólnie) niejasny trik , aby włączyć indexOf()
„y znalezione wartości zwracanej do truthy (robiąc Nie znaleziono jak falsy ) i ludzie często używają go do jej skutkiem ubocznym obcinania numery do 32 bitów (i upuszczając swoje miejsce dziesiętne przez podwojenie go, efektywnie tak samo jak Math.floor()
dla liczb dodatnich).
Mówię niejasno, ponieważ nie jest od razu oczywiste, do czego jest używany. Zasadniczo chcesz, aby Twój kod komunikował się wyraźnie z innymi czytającymi go osobami. Chociaż używanie ~
może wyglądać fajnie , jest na ogół zbyt sprytne dla własnego dobra. :)
Jest również mniej aktualne, ponieważ JavaScript ma Array.prototype.includes()
i String.prototype.includes()
. Zwracają one wartość logiczną. Jeśli platforma docelowa to obsługuje, powinieneś to preferować do testowania na obecność wartości w łańcuchu lub tablicy.
value = value || default
w JavaScript jest powszechnym i poprawnym idiomem, o ile wiesz, kiedy możesz i nie możesz go używać.
v = t ? a : b;
. Uważam, że jest to znacznie wyraźniejsze niż var v; if (t} { v = a; } else { v = b; }
zwykle w podziale na linie 5+, a także jaśniejsze niż var v = b; if (t) { v = a; }
zwykle na liniach 4+. Ale znam wiele osób, które nie znają ? :
operatorów, którzy wolą drugi lub trzeci sposób. Uważam, że pierwszy jest bardziej czytelny. Zgadzam się z ogólną zasadą, wyjaśniaj kod, nie używaj hacków. Wydaje mi się, że widzę ~v.indexOf('...')
to bardzo wyraźnie, gdy się tego nauczę.
~
idiomatycznym. technicznie jest to część specyfikacji językowej , ale nie jest tak bardzo częścią ogólnego języka .
Używanie go przed indexOf()
wyrażeniem skutecznie daje wynik prawdziwości / fałszowania zamiast indeksu numerycznego, który jest bezpośrednio zwracany.
Jeśli wartość jest równa -1
, a ~-1
to 0
dlatego, że -1
to łańcuch wszystkich bitów 1. Każda wartość większa lub równa zero da wynik niezerowy. A zatem,
if (~someString.indexOf(something)) {
}
spowoduje uruchomienie if
kodu, gdy „coś” znajdzie się w „someString”. Jeśli spróbujesz użyć .indexOf()
bezpośrednio jako wartość logiczną, to nie zadziała, ponieważ czasami zwraca zero (gdy „coś” znajduje się na początku łańcucha).
Oczywiście to też działa:
if (someString.indexOf(something) >= 0) {
}
i jest znacznie mniej tajemniczy.
Czasami zobaczysz to również:
var i = ~~something;
~
Dwukrotne użycie operatora jest szybkim sposobem przekonwertowania łańcucha na 32-bitową liczbę całkowitą. Pierwszy ~
dokonuje konwersji, a drugi ~
odwraca bity. Oczywiście, jeśli operator zostanie zastosowany do czegoś, czego nie można przekonwertować na liczbę, otrzymasz NaN
w rezultacie. ( edytuj - tak naprawdę to drugie ~
jest stosowane jako pierwsze, ale masz pomysł.)
~
gdy wykonywane na liczbach całkowitych jest równa -(x + 1)
.
0
bycia false
i niezerowa byt true
sięga wstecz, przynajmniej do C w latach 70. i prawdopodobnie wielu innych ówczesnych języków programowania systemów. Prawdopodobnie wynika to ze sposobu działania sprzętu; wiele procesorów ustawia bit zerowy po operacji i posiada odpowiednią instrukcję rozgałęzienia, aby go przetestować.
| 0
, w takim przypadku jest to tylko jedna operacja.
~~
dokładnie w ten sam sposób.
~
Jest bitowe NOT Operator , ~x
jest mniej więcej taka sama jak -(x+1)
. W pewnym sensie łatwiej to zrozumieć. Więc:
~2; // -(2+1) ==> -3
Zastanów się -(x+1)
. -1
może wykonać tę operację, aby utworzyć 0
.
Innymi słowy, ~
użycie z zakresem wartości liczbowych spowoduje wygenerowanie wartości fałszowania (przymusu do false
od 0
) tylko dla -1
wartości wejściowej, w przeciwnym razie dla każdej innej wartości prawdziwej.
Jak wiemy, -1
jest powszechnie nazywany wartością wartownika . Jest on używany do wielu funkcji, które zwracają >= 0
wartości do sukcesu i -1
do awarii w języku C. Która ta sama zasada zwrotu wartości indexOf()
w JavaScript.
W ten sposób często sprawdza się obecność / brak podłańcucha w innym ciągu
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
}
Łatwiej byłoby to jednak zrobić, ~
jak poniżej
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)
gdybym zobaczył to w oświadczeniu „if”. Tylda mówi mi dokładnie, co robi, aby zrekompensować naturę JavaScript opartą na 0. Także im mniej nawiasów, tym lepiej do czytania
if (a.indexOf("Ba") > -1) {// found} //true
który, choć nieco dłuższy niż przykłady tyldy, jest znacznie mniejszy niż dwa podane przykłady, a dla nowych programistów var opinion = !~-1 ? 'more' : 'less'
zrozumiałe.
~indexOf(item)
pojawia się dość często, a odpowiedzi tutaj są świetne, ale może niektórzy ludzie muszą po prostu wiedzieć, jak go używać i „pomijać” teorię:
if (~list.indexOf(item)) {
// item in list
} else {
// item *not* in list
}
++
a --
ponieważ „zachęca do nadmiernej podstępu”, a jednak jakoś ~
przetrwał ( czając się
list.indexOf(item) >= 0
lub ... > -1
ponieważ javascript jest zerowy i nie zdecydował się rozwiązać tego od samego początku. Ponadto, tylko opinia (taka sama jak Airbnb), każdy, kto robi coś sensownego w javascript, wie ++
i chociaż --
jest mniej powszechny, znaczenie można wywnioskować.
++
i --
od jakiegoś czasu z powodu prymitywnych metod, takich jak map
, forEach
itp. Chodzi mi bardziej o to, dlaczego nie uważali też za ~
zbyt skomplikowane, gdy jakikolwiek używany standard obejmuje operatory zwiększania i zmniejszania. Zabraniać czegoś, więc CIS101 nie ma żadnego sensu.
Dla tych, którzy rozważają użycie tyldy, aby stworzyć prawdziwą wartość z indexOf
wyniku, jest ona bardziej wyraźna i ma mniej magii, aby zamiast tego użyć tej includes
metodyString
.
'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false
Pamiętaj, że jest to nowa standardowa metoda od ES 2015, więc nie będzie działać na starszych przeglądarkach. W przypadkach, w których ma to znaczenie, rozważ użycie String.prototype.includes polifill .
Ta funkcja jest również dostępna dla tablic używających tej samej składni :
['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false
Oto Array.prototype.inc. Zawiera polifill, jeśli potrzebujesz starszej obsługi przeglądarki.