Risposte:
~è un operatore bit a bit che capovolge tutti i bit nel suo operando.
Ad esempio, se il tuo numero fosse 1, la sua rappresentazione binaria del float IEEE 754 (come JavaScript tratta i numeri) sarebbe ...
0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Quindi ~converte il suo operando in un numero intero a 32 bit (lo fanno gli operatori bit a bit in JavaScript) ...
0000 0000 0000 0000 0000 0000 0000 0001
Se fosse un numero negativo, sarebbe memorizzato nel complemento di 2: inverti tutti i bit e aggiungi 1.
... e poi lancia tutti i suoi bit ...
1111 1111 1111 1111 1111 1111 1111 1110
Allora, a che cosa serve? Quando si potrebbe mai usarlo?
Ha parecchi usi. Se stai scrivendo cose di basso livello, è utile. Se hai profilato la tua applicazione e trovato un collo di bottiglia, potrebbe essere reso più performante usando trucchi bit a bit (come uno strumento possibile in una borsa molto più grande).
È anche un trucco (generalmente) poco chiaro per trasformare indexOf()il valore di ritorno trovato in verità (pur non trovandolo come falsa ) e le persone spesso lo usano per il suo effetto collaterale di troncare i numeri a 32 bit (e far cadere il suo decimale raddoppiandolo, effettivamente lo stesso che Math.floor()per i numeri positivi).
Dico poco chiaro perché non è immediatamente ovvio per cosa viene utilizzato. In genere, si desidera che il codice comunichi chiaramente alle altre persone che lo leggono. Mentre l'utilizzo ~può sembrare interessante , è generalmente troppo intelligente per il suo bene. :)
È anche meno rilevante ora che JavaScript ha Array.prototype.includes()e String.prototype.includes(). Questi restituiscono un valore booleano. Se la tua piattaforma di destinazione lo supporta, dovresti preferirlo per verificare l'esistenza di un valore in una stringa o matrice.
value = value || defaultin JavaScript è un linguaggio comune e valido fintanto che sai quando puoi e non puoi usarlo.
v = t ? a : b;. Trovo che sia molto più chiaro del var v; if (t} { v = a; } else { v = b; }solito suddiviso su 5+ righe e anche più chiaro di quello var v = b; if (t) { v = a; }che di solito sarebbe 4+ righe. Ma conosco molte persone che non hanno familiarità con gli ? :operatori che preferirebbero la seconda o la terza via. Trovo che il primo sia più leggibile. Sono d'accordo con il principio generale, chiarisco il codice, non usare gli hack. Immagino di vedere ~v.indexOf('...')molto chiaro una volta che l'ho imparato.
~idiomatico. fa tecnicamente parte delle specifiche del linguaggio , ma non fa tanto parte del linguaggio in uso generale .
indexOf()Usarlo prima di un'espressione ti dà effettivamente un risultato di verità / falsità invece dell'indice numerico che viene restituito direttamente.
Se il valore restituito è -1, allora ~-1è 0perché -1è una stringa di tutti e 1 i bit. Qualsiasi valore maggiore o uguale a zero darà un risultato diverso da zero. Così,
if (~someString.indexOf(something)) {
}
farà ifeseguire il codice quando "qualcosa" è in "someString". Se provi a usarlo .indexOf()direttamente come booleano, allora non funzionerà perché a volte restituisce zero (quando "qualcosa" è all'inizio della stringa).
Naturalmente funziona anche questo:
if (someString.indexOf(something) >= 0) {
}
ed è notevolmente meno misterioso.
A volte vedrai anche questo:
var i = ~~something;
Usare l' ~operatore due volte in questo modo è un modo rapido per convertire una stringa in un numero intero a 32 bit. Il primo ~esegue la conversione e il secondo ~ribalta i bit. Naturalmente se l'operatore viene applicato a qualcosa che non può essere convertito in un numero, si ottiene NaNdi conseguenza. ( modifica - in realtà è il secondo ~che viene applicato per primo, ma ottieni l'idea.)
~quando eseguito su numeri interi è uguale a -(x + 1).
0dell'essere falsee dell'essere diverso da zero truerisale a molto tempo fa, almeno a C negli anni '70 e probabilmente molti altri linguaggi di programmazione di sistemi allora contemporanei. Probabilmente deriva dal modo in cui funziona l'hardware; molte CPU impostano un bit zero dopo un'operazione e dispongono di un'istruzione di ramo corrispondente per testarla.
| 0, nel qual caso è una sola operazione.
~~esattamente allo stesso modo.
Il ~è Bitwise NON Operator , ~xè più o meno lo stesso di -(x+1). È più facile da capire, in un certo senso. Così:
~2; // -(2+1) ==> -3
Prendere in considerazione -(x+1). -1può eseguire quell'operazione per produrre a 0.
In altre parole, ~usato con un intervallo di valori numerici produrrà un valore falso (coerce to falsefrom 0) solo per il -1valore di input, altrimenti qualsiasi altro valore di verità.
Come sappiamo, -1viene comunemente chiamato un valore sentinella . È usato per molte funzioni che restituiscono >= 0valori per il successo e -1per il fallimento nel linguaggio C. Che la stessa regola del valore di ritorno di indexOf()in JavaScript.
In questo modo è comune verificare la presenza / assenza di una sottostringa in un'altra stringa
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
}
Tuttavia, sarebbe più facile farlo ~come di seguito
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)se lo vedessi in una dichiarazione if. La tilde mi dice esattamente cosa sta facendo per compensare la natura basata su 0 di Javascript. Inoltre, meno parentesi meglio è per la lettura
if (a.indexOf("Ba") > -1) {// found} //truequale, sebbene un po 'più lungo degli esempi di tilde, è considerevolmente inferiore ai due esempi che hai dato e per i nuovi programmatori var opinion = !~-1 ? 'more' : 'less'comprensibili.
~indexOf(item) arriva abbastanza spesso, e le risposte qui sono fantastiche, ma forse alcune persone hanno solo bisogno di sapere come usarlo e "saltare" la teoria:
if (~list.indexOf(item)) {
// item in list
} else {
// item *not* in list
}
++e --perché "incoraggiano l'eccessiva inganno" e tuttavia in qualche modo sono ~sopravvissuti (in agguato nell'ombra) github.com/airbnb/javascript/issues/540
list.indexOf(item) >= 0o ... > -1poiché javascript è basato su zero e non ha scelto di affrontarlo sin dall'inizio. Inoltre, solo l'opinione (come quella di Airbnb), chiunque stia facendo qualcosa di significativo in javascript lo sa ++, e mentre --è meno comune, il significato può essere dedotto.
++e --per un po 'a causa di metodi primitivi come map, forEachecc. Il mio punto è più sul perché non considerano anche ~eccessivamente complicato quando qualunque standard utilizzato include operatori di incremento e decremento. Proibire qualcosa in modo che CIS101 non abbia alcun senso.
Per coloro che considerano l'utilizzo del trucco della tilde per creare un valore veritiero da un indexOfrisultato, è più esplicito e ha meno magia invece di usare il includesmetodoString .
'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false
Si noti che questo è un nuovo metodo standard a partire da ES 2015, quindi non funzionerà su browser meno recenti. Nei casi in cui ciò è importante, prendere in considerazione l'uso di String.prototype.includes polyfill .
Questa funzione è disponibile anche per le matrici che utilizzano la stessa sintassi :
['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false
Ecco il file polifill Array.prototype.incles se hai bisogno del supporto del browser precedente.