Cosa fa una tilde quando precede un’espressione?

var attr = ~'input,textarea'.indexOf( target.tagName.toLowerCase() ) ? 'value' : 'innerHTML' 

L’ho visto in una risposta, e non l’ho mai visto prima.

Cosa significa?

~ è un operatore bit a bit che capovolge tutti i bit nel suo operando.

Ad esempio, se il tuo numero era 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 (gli operatori bit a bit in JavaScript lo fanno) …

 0000 0000 0000 0000 0000 0000 0000 0001 

Se fosse un numero negativo, verrebbe memorizzato nel complemento a 2: invertire tutti i bit e aggiungere 1.

… e poi capovolge tutti i suoi bit …

 1111 1111 1111 1111 1111 1111 1111 1110 

Allora, a che serve? Quando potrebbe mai usarlo?

Ha un buon numero di usi. Se stai scrivendo cose di basso livello, è comodo. Se hai profilato la tua applicazione e trovato un collo di bottiglia, potrebbe essere reso più performante usando i trucchi bit a bit (come un ansible strumento in una borsa molto più grande).

E ‘anche un trucco (generalmente) non chiaro per trasformare il valore di ritorno trovato di indexOf () in verità (mentre non viene trovato come falsa ) e le persone lo usano spesso per il suo effetto collaterale di troncare i numeri a 32 bit (e abbassare la sua posizione decimale di raddoppiandolo, in pratica uguale a Math.floor() per i numeri positivi).

Dico poco chiaro perché non è immediatamente evidente per cosa viene usato. In generale, vuoi che il tuo codice comunichi chiaramente ad altre persone che lo leggono. Mentre usare ~ 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 testare l’esistenza di un valore in una stringa o array.

Usarlo prima che un’espressione indexOf indexOf() fornisca effettivamente un risultato di verità / falsità invece dell’indice numerico che viene restituito direttamente.

Se il valore di ritorno è -1 , allora ~-1 è 0 perché -1 è una stringa di tutti i 1 bit. Qualsiasi valore maggiore o uguale a zero darà un risultato diverso da zero. Così,

 if (~someString.indexOf(something)) { } 

causerà l’esecuzione del codice if quando “qualcosa” è in “someString”. Se provi ad usare direttamente .indexOf() come booleano, allora non funzionerà perché a volte restituisce zero (quando “qualcosa” è all’inizio della stringa).

Naturalmente, anche questo funziona:

 if (someString.indexOf(something) >= 0) { } 

ed è considerevolmente meno misterioso.

A volte vedrai anche questo:

 var i = ~~something; 

Usare l’operatore ~ due volte è un modo rapido per convertire una stringa in un numero intero a 32 bit. Il primo ~ esegue la conversione e il secondo ~ capovolge i bit. Ovviamente se l’operatore è applicato a qualcosa che non può essere convertito in un numero, si ottiene NaN come risultato. ( modifica – in realtà è il secondo ~ che viene applicato per primo, ma ottieni l’idea.)

Il ~ è Operatore NOT bit a bit , ~x è grosso modo uguale a -(x+1) . È più facile da capire, una specie di. Così:

 ~2; // -(2+1) ==> -3 

Considera -(x+1) . -1 può eseguire quell’operazione per produrre uno 0 .

In altre parole, ~ usato con un intervallo di valori numerici produrrà un valore falsy ( falsy to false from 0 ) solo per il valore di input -1 , altrimenti qualsiasi altro valore di truthy .

Come sappiamo, -1 è comunemente chiamato valore sentinella . Viene utilizzato per molte funzioni che restituiscono valori >= 0 per il successo e -1 per errori nel linguaggio C Quale la stessa regola del valore di ritorno di indexOf() in JavaScript.

In questo modo è comune verificare la presenza / assenza di una substring in un’altra string

 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 attraverso ~ come sotto

 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 } 

~indexOf(item) si presenta abbastanza spesso, e le risposte qui sono grandiose, 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 } 

Per coloro che pensano di usare il trucco tilde per creare un valore vero da un risultato indexOf , è più esplicito e ha meno magia per usare invece il metodo includes su String .

 '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à con i browser più vecchi. Nei casi in cui ciò è importante, considerare l’utilizzo di String.prototype.include il polyfill .

Questa funzione è disponibile anche per gli array che utilizzano la stessa syntax :

 ['apples', 'oranges', 'cherries'].includes('apples') //=> true ['apples', 'oranges', 'cherries'].includes('unicorns') //=> false 

Qui è il Array.prototype.include polyfill se hai bisogno di un supporto browser più vecchio.