Respuestas:
~
es un operador bit a bit que voltea todos los bits en su operando.
Por ejemplo, si su número fuera 1
, su representación binaria del flotador IEEE 754 (cómo trata JavaScript los números) sería ...
0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Entonces ~
convierte su operando a un entero de 32 bits (los operadores bit a bit en JavaScript hacen eso) ...
0000 0000 0000 0000 0000 0000 0000 0001
Si fuera un número negativo, se almacenaría en el complemento de 2: invierta todos los bits y agregue 1.
... y luego voltea todos sus bits ...
1111 1111 1111 1111 1111 1111 1111 1110
Entonces, ¿para qué sirve? ¿Cuándo podría uno usarlo?
Tiene bastantes usos. Si estás escribiendo cosas de bajo nivel, es útil. Si ha perfilado su aplicación y ha encontrado un cuello de botella, podría ser más eficaz mediante el uso de trucos bit a bit (como una posible herramienta en una bolsa mucho más grande).
También es un truco (generalmente) poco claro para convertir indexOf()
el valor de retorno encontrado en verdadero (mientras que no se encuentra como falso ) y la gente lo usa a menudo por su efecto secundario de truncar números a 32 bits (y soltar su decimal al duplicarlo) efectivamente lo mismo que Math.floor()
para los números positivos).
Digo que no está claro porque no es inmediatamente obvio para qué se está utilizando. En general, desea que su código se comunique claramente con otras personas que lo leen. Si bien el uso ~
puede verse bien , generalmente es demasiado inteligente para su propio bien. :)
También es menos relevante ahora que JavaScript tiene Array.prototype.includes()
y String.prototype.includes()
. Estos devuelven un valor booleano. Si su (s) plataforma (s) de destino lo admiten, debería preferir esto para probar la existencia de un valor en una cadena o matriz.
value = value || default
en JavaScript es un idioma común y válido siempre que sepa cuándo puede y no puede usarlo.
v = t ? a : b;
. Me parece mucho más claro de var v; if (t} { v = a; } else { v = b; }
lo que normalmente se divide en más de 5 líneas y también más claro de var v = b; if (t) { v = a; }
lo que normalmente sería 4+ líneas. Pero conozco a muchas personas que no están familiarizadas con los ? :
operadores que preferirían la segunda o tercera vía. Me parece que el primero es más legible. Estoy de acuerdo con el principio general, aclare el código, no use hacks. Supongo que solo veo ~v.indexOf('...')
que es muy claro una vez que lo he aprendido.
~
idiomático. técnicamente es parte de la especificación del lenguaje , pero no es tanto parte del lenguaje en uso general .
Usarlo antes de una indexOf()
expresión efectivamente le da un resultado verdadero / falso en lugar del índice numérico que se devuelve directamente.
Si el valor de retorno es -1
, entonces ~-1
es 0
porque -1
es una cadena de todos los 1 bits. Cualquier valor mayor o igual a cero dará un resultado distinto de cero. Así,
if (~someString.indexOf(something)) {
}
hará que el if
código se ejecute cuando "algo" esté en "someString". Si intenta usarlo .indexOf()
directamente como booleano, eso no funcionará porque a veces devuelve cero (cuando "algo" está al comienzo de la cadena).
Por supuesto, esto también funciona:
if (someString.indexOf(something) >= 0) {
}
y es considerablemente menos misterioso
A veces también verás esto:
var i = ~~something;
Usar el ~
operador dos veces así es una forma rápida de convertir una cadena a un entero de 32 bits. El primero ~
realiza la conversión y el segundo ~
voltea los bits. Por supuesto, si el operador se aplica a algo que no se puede convertir a un número, se obtiene NaN
como resultado. ( editar - en realidad es el segundo ~
que se aplica primero, pero se entiende la idea).
~
cuando se realiza en enteros es igual a -(x + 1)
.
0
ser false
y el ser distinto de cero true
se remontan, al menos, a C en los años 70 y probablemente a muchos otros lenguajes de programación de sistemas contemporáneos. Probablemente se deba a la forma en que funciona el hardware; muchas CPU establecen un bit cero después de una operación y tienen una instrucción de bifurcación correspondiente para probarlo.
| 0
, en cuyo caso es su única operación.
~~
exactamente de la misma manera.
El ~
es NOT en modo bit del operador , ~x
es más o menos lo mismo que -(x+1)
. Es más fácil de entender, más o menos. Entonces:
~2; // -(2+1) ==> -3
Considere -(x+1)
. -1
puede realizar esa operación para producir a 0
.
En otras palabras, si se ~
usa con un rango de valores numéricos, se producirá un valor falso (coacción a false
partir de 0
) solo para el -1
valor de entrada; de lo contrario, cualquier otro valor verdadero.
Como sabemos, -1
comúnmente se llama valor centinela . Se utiliza para muchas funciones que devuelven >= 0
valores para el éxito y -1
para el fracaso en lenguaje C. Que la misma regla de valor de retorno de indexOf()
en JavaScript.
Es común verificar la presencia / ausencia de una subcadena en otra cadena de esta manera
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
}
Sin embargo, sería más fácil hacerlo de la ~
siguiente manera
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)
si lo viera en una declaración if. La tilde me dice exactamente qué está haciendo para compensar la naturaleza basada en 0 de Javascript. Además, cuanto menos paréntesis, mejor para leer
if (a.indexOf("Ba") > -1) {// found} //true
, lo que, aunque es un poco más largo que los ejemplos de tilde, es considerablemente menor que los dos ejemplos que dio y para los nuevos programadores var opinion = !~-1 ? 'more' : 'less'
comprensibles.
~indexOf(item)
surge con bastante frecuencia, y las respuestas aquí son geniales, pero tal vez algunas personas solo necesitan saber cómo usarlo y "omitir" la teoría:
if (~list.indexOf(item)) {
// item in list
} else {
// item *not* in list
}
++
y --
porque "fomentan el engaño excesivo" y, sin embargo, de alguna manera ~
sobrevivieron (acechando en las sombras) github.com/airbnb/javascript/issues/540
list.indexOf(item) >= 0
o ... > -1
ya que javascript está basado en cero y no eligió abordar esto desde el principio. Además, solo la opinión (igual que la de Airbnb), cualquiera que esté haciendo algo significativo en JavaScript lo sabe ++
, y aunque --
es menos común, se puede inferir el significado.
++
y hace --
un tiempo debido a métodos primitivos como map
, forEach
etc. Mi punto es más sobre por qué no consideraron ~
demasiado complicado cuando cualquier estándar utilizado incluye operadores de incremento y decremento. Prohibir algo para que CIS101 no tenga ningún sentido.
Para aquellos que consideran usar el truco tilde para crear un valor verdadero a partir de un indexOf
resultado, es más explícito y tiene menos magia para usar el includes
métodoString
.
'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false
Tenga en cuenta que este es un nuevo método estándar a partir de ES 2015, por lo que no funcionará en navegadores antiguos. En los casos en que eso sea importante, considere usar el String.prototype.includes polyfill .
Esta característica también está disponible para matrices que usan la misma sintaxis :
['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false
Aquí está el Array.prototype.incluye polyfill si necesita soporte de navegador más antiguo.