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 || default
in 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
è 0
perché -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à if
eseguire 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 NaN
di conseguenza. ( modifica - in realtà è il secondo ~
che viene applicato per primo, ma ottieni l'idea.)
~
quando eseguito su numeri interi è uguale a -(x + 1)
.
0
dell'essere false
e dell'essere diverso da zero true
risale 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)
. -1
può eseguire quell'operazione per produrre a 0
.
In altre parole, ~
usato con un intervallo di valori numerici produrrà un valore falso (coerce to false
from 0
) solo per il -1
valore di input, altrimenti qualsiasi altro valore di verità.
Come sappiamo, -1
viene comunemente chiamato un valore sentinella . È usato per molte funzioni che restituiscono >= 0
valori per il successo e -1
per 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} //true
quale, 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) >= 0
o ... > -1
poiché 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
, forEach
ecc. 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 indexOf
risultato, è più esplicito e ha meno magia invece di usare il includes
metodoString
.
'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.