Buscar..
Observaciones
Cuando se utiliza la coerción booleana, los siguientes valores se consideran "falsos" :
-
false
-
0
-
""
(cadena vacía) -
null
-
undefined
-
NaN
(no es un número, por ejemplo,0/0
) -
document.all
¹ (contexto del navegador)
Todo lo demás se considera "veraz" .
Violation violación voluntaria de la especificación ECMAScript
Operadores logicos con booleanos
var x = true,
y = false;
Y
Este operador devolverá verdadero si ambas expresiones se evalúan como verdaderas. Este operador booleano empleará un cortocircuito y no evaluará y
si x
evalúa como false
.
x && y;
Esto devolverá falso, porque y
es falso.
O
Este operador devolverá verdadero si una de las dos expresiones se evalúa como verdadera. Este operador booleano empleará cortocircuito e y
no se evaluará si x
evalúa como true
.
x || y;
Esto devolverá verdadero, porque x
es verdadero.
NO
Este operador devolverá false si la expresión de la derecha se evalúa como true, y devolverá true si la expresión de la derecha se evalúa como false.
!x;
Esto devolverá falso, porque x
es verdadero.
Igualdad abstracta (==)
Los operandos del operador de igualdad abstracta se comparan después de convertirse a un tipo común. Cómo se realiza esta conversión se basa en la especificación del operador:
Especificación para el operador ==
:
7.2.13 Comparación de igualdad abstracta
La comparaciónx == y
, dondex
ey
son valores, producetrue
ofalse
. Tal comparación se realiza de la siguiente manera:
- Si el
Type(x)
es el mismo que elType(y)
, entonces:
- a. Devuelve el resultado de realizar una comparación de igualdad estricta
x === y
.
- Si
x
esnull
ey
undefined
estáundefined
, devuelvatrue
.- Si
x
undefined
estáundefined
yy
esnull
, devuelvatrue
.- Si el
Type(x)
esNumber
y elType(y)
esString
, devuelva el resultado de la comparaciónx == ToNumber(y)
.- Si el
Type(x)
esString
y elType(y)
esNumber
, devuelva el resultado de la comparación aToNumber(x) == y
.- Si el
Type(x)
esBoolean
, devuelva el resultado de la comparación aToNumber(x) == y
.- Si el
Type(y)
esBoolean
, devuelva el resultado de lacomparison x == ToNumber(y)
.- Si el
Type(x)
esString
,Number
oSymbol
y elType(y)
esObject
, devuelva el resultado de la comparaciónx == ToPrimitive(y)
.- Si el
Type(x)
es Objeto y elType(y)
esString
,Number
oSymbol
, devuelva el resultado de la comparaciónToPrimitive(x) == y
.- Devuelve
false
Ejemplos:
1 == 1; // true
1 == true; // true (operand converted to number: true => 1)
1 == '1'; // true (operand converted to number: '1' => 1 )
1 == '1.00'; // true
1 == '1.00000000001'; // false
1 == '1.00000000000000001'; // true (true due to precision loss)
null == undefined; // true (spec #2)
1 == 2; // false
0 == false; // true
0 == undefined; // false
0 == ""; // true
Operadores relacionales (<, <=,>,> =)
Cuando ambos operandos son numéricos, se comparan normalmente:
1 < 2 // true
2 <= 2 // true
3 >= 5 // false
true < false // false (implicitly converted to numbers, 1 > 0)
Cuando ambos operandos son cadenas, se comparan lexicográficamente (de acuerdo con el orden alfabético):
'a' < 'b' // true
'1' < '2' // true
'100' > '12' // false ('100' is less than '12' lexicographically!)
Cuando un operando es una cadena y el otro es un número, la cadena se convierte en un número antes de la comparación:
'1' < 2 // true
'3' > 2 // true
true > '2' // false (true implicitly converted to number, 1 < 2)
Cuando la cadena no es numérica, la conversión numérica devuelve NaN
(no es un número). Comparando con NaN
siempre devuelve false
:
1 < 'abc' // false
1 > 'abc' // false
Pero tenga cuidado al comparar un valor numérico con cadenas null
, undefined
o vacías:
1 > '' // true
1 < '' // false
1 > null // true
1 < null // false
1 > undefined // false
1 < undefined // false
Cuando un operando es un objeto y el otro es un número, el objeto se convierte en un número antes de la comparación. Por lo tanto, null
es un caso particular porque Number(null);//0
new Date(2015)< 1479480185280 // true
null > -1 //true
({toString:function(){return 123}}) > 122 //true
Desigualdad
Operator !=
Es el inverso del operador ==
.
Devolverá true
si los operandos no son iguales.
El motor de javascript intentará convertir ambos operandos a tipos coincidentes si no son del mismo tipo. Nota: si los dos operandos tienen diferentes referencias internas en la memoria, entonces se devolverá false
.
Muestra:
1 != '1' // false
1 != 2 // true
En el ejemplo anterior, 1 != '1'
es false
porque se está comparando un tipo de número primitivo con un valor char
. Por lo tanto, el motor de Javascript no se preocupa por el tipo de datos del valor RHS.
Operador !==
es el inverso del operador ===
. Devolverá verdadero si los operandos no son iguales o si sus tipos no coinciden.
Ejemplo:
1 !== '1' // true
1 !== 2 // true
1 !== 1 // false
Operadores lógicos con valores no booleanos (coerción booleana)
El OR lógico ( ||
), leyendo de izquierda a derecha, evaluará el primer valor verdadero . Si no se encuentra un valor verdadero , se devuelve el último valor.
var a = 'hello' || ''; // a = 'hello'
var b = '' || []; // b = []
var c = '' || undefined; // c = undefined
var d = 1 || 5; // d = 1
var e = 0 || {}; // e = {}
var f = 0 || '' || 5; // f = 5
var g = '' || 'yay' || 'boo'; // g = 'yay'
AND lógico ( &&
), leyendo de izquierda a derecha, evaluará el primer valor falso . Si no se encuentra ningún valor falsey , se devuelve el último valor.
var a = 'hello' && ''; // a = ''
var b = '' && []; // b = ''
var c = undefined && 0; // c = undefined
var d = 1 && 5; // d = 5
var e = 0 && {}; // e = 0
var f = 'hi' && [] && 'done'; // f = 'done'
var g = 'bye' && undefined && 'adios'; // g = undefined
Este truco se puede usar, por ejemplo, para establecer un valor predeterminado para un argumento de función (antes de ES6).
var foo = function(val) {
// if val evaluates to falsey, 'default' will be returned instead.
return val || 'default';
}
console.log( foo('burger') ); // burger
console.log( foo(100) ); // 100
console.log( foo([]) ); // []
console.log( foo(0) ); // default
console.log( foo(undefined) ); // default
Solo tenga en cuenta que para los argumentos, 0
y (en menor medida) la cadena vacía a menudo también son valores válidos que deberían poder pasar explícitamente y anular un valor predeterminado, que, con este patrón, no lo harán (porque son falsos ).
Nulo e indefinido
Las diferencias entre null
e undefined
null
e undefined
comparten igualdad abstracta ==
pero no estricta igualdad ===
,
null == undefined // true
null === undefined // false
Representan cosas ligeramente diferentes:
-
undefined
representa la ausencia de un valor , como antes de que se haya creado un identificador / propiedad Objeto o en el período entre el identificador / parámetro de función de creación y su primer conjunto, si lo hubiera. -
null
representa la ausencia intencional de un valor para un identificador o propiedad que ya se ha creado.
Son diferentes tipos de sintaxis:
-
undefined
es una propiedad del Objeto global , generalmente inmutable en el ámbito global. Esto significa que en cualquier lugar donde pueda definir un identificador que no sea el espacio de nombres global podría esconderseundefined
de ese alcance (aunque las cosas todavía pueden estarundefined
) -
null
es una palabra literal , por lo que su significado nunca puede cambiarse e intentar hacerlo generará un error .
Las similitudes entre null
e undefined
null
e undefined
son falsos.
if (null) console.log("won't be logged");
if (undefined) console.log("won't be logged");
Ni null
ni undefined
igual false
(vea esta pregunta ).
false == undefined // false
false == null // false
false === undefined // false
false === null // false
Usando undefined
- Si no se puede confiar en el alcance actual, use algo que se evalúe como indefinido , por ejemplo,
void 0;
. - Si
undefined
está sombreado por otro valor, es tan malo como sombrearArray
oNumber
. - Evita establecer algo como
undefined
. Si desea eliminar una barra de propiedades de un objetofoo
,delete foo.bar;
en lugar. - El identificador de prueba de existencia
foo
contraundefined
podría generar un error de referencia , en su lugar usetypeof foo
contra"undefined"
.
Propiedad NaN del objeto global
NaN
(" N ot a N umber") es un valor especial definido por el Estándar IEEE para la aritmética de punto flotante , que se usa cuando se proporciona un valor no numérico pero se espera un número ( 1 * "two"
), o cuando un cálculo no tiene un resultado de number
válido ( Math.sqrt(-1)
).
Cualquier comparación de igualdad o relacional con NaN
devuelve false
, incluso comparándolo con sí mismo. Porque, se supone que NaN
denota el resultado de un cálculo sin sentido, y como tal, no es igual al resultado de cualquier otro cálculo sin sentido.
(1 * "two") === NaN //false
NaN === 0; // false
NaN === NaN; // false
Number.NaN === NaN; // false
NaN < 0; // false
NaN > 0; // false
NaN > 0; // false
NaN >= NaN; // false
NaN >= 'two'; // false
Las comparaciones no iguales siempre devolverán true
:
NaN !== 0; // true
NaN !== NaN; // true
Comprobando si un valor es NaN
Puede probar un valor o expresión para NaN
usando la función Number.isNaN () :
Number.isNaN(NaN); // true
Number.isNaN(0 / 0); // true
Number.isNaN('str' - 12); // true
Number.isNaN(24); // false
Number.isNaN('24'); // false
Number.isNaN(1 / 0); // false
Number.isNaN(Infinity); // false
Number.isNaN('str'); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false
Puede verificar si un valor es NaN
comparándolo consigo mismo:
value !== value; // true for NaN, false for any other value
Puedes usar el siguiente polyfill para Number.isNaN()
:
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
Por el contrario, la función global isNaN()
devuelve true
no solo para NaN
, sino también para cualquier valor o expresión que no se pueda forzar a un número:
isNaN(NaN); // true
isNaN(0 / 0); // true
isNaN('str' - 12); // true
isNaN(24); // false
isNaN('24'); // false
isNaN(Infinity); // false
isNaN('str'); // true
isNaN(undefined); // true
isNaN({}); // true
ECMAScript define un algoritmo de "similitud" llamado SameValue
que, desde ECMAScript 6, se puede invocar con Object.is
. A diferencia de la comparación ==
y ===
, usar Object.is()
tratará a NaN
como idéntico a sí mismo (y -0
como no idéntico a +0
):
Object.is(NaN, NaN) // true
Object.is(+0, 0) // false
NaN === NaN // false
+0 === 0 // true
Puede usar el siguiente polyfill para Object.is()
(de MDN ):
if (!Object.is) {
Object.is = function(x, y) {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
};
}
Puntos a tener en cuenta
NaN en sí es un número, lo que significa que no es igual a la cadena "NaN", y lo más importante (aunque quizás de manera no intuitiva):
typeof(NaN) === "number"; //true
Cortocircuito en operadores booleanos.
El operador-e ( &&
) y el operador-o ( ||
) emplean cortocircuitos para evitar trabajos innecesarios si el resultado de la operación no cambia con el trabajo adicional.
En x && y
, y
no se evaluará si x
evalúa como false
, porque se garantiza que toda la expresión es false
.
En x || y
, y
no se evaluará si x
evalúa como true
, porque se garantiza que toda la expresión es true
.
Ejemplo con funciones
Tome las siguientes dos funciones:
function T() { // True
console.log("T");
return true;
}
function F() { // False
console.log("F");
return false;
}
Ejemplo 1
T() && F(); // false
Salida:
'T'
'F'
Ejemplo 2
F() && T(); // false
Salida:
'F'
Ejemplo 3
T() || F(); // true
Salida:
'T'
Ejemplo 4
F() || T(); // true
Salida:
'F'
'T'
Cortocircuito para evitar errores.
var obj; // object has value of undefined
if(obj.property){ }// TypeError: Cannot read property 'property' of undefined
if(obj.property && obj !== undefined){}// Line A TypeError: Cannot read property 'property' of undefined
Línea A: si invierte el orden, la primera declaración condicional evitará el error en el segundo al no ejecutarlo si arrojaría el error
if(obj !== undefined && obj.property){}; // no error thrown
Pero solo se debe usar si esperas undefined
if(typeof obj === "object" && obj.property){}; // safe option but slower
Cortocircuito para proporcionar un valor predeterminado
El ||
El operador se puede usar para seleccionar un valor "verdadero" o el valor predeterminado.
Por ejemplo, esto se puede usar para asegurar que un valor anulable se convierta en un valor no anulable:
var nullableObj = null;
var obj = nullableObj || {}; // this selects {}
var nullableObj2 = {x: 5};
var obj2 = nullableObj2 || {} // this selects {x: 5}
O devolver el primer valor de verdad.
var truthyValue = {x: 10};
return truthyValue || {}; // will return {x: 10}
Lo mismo se puede usar para retroceder varias veces:
envVariable || configValue || defaultConstValue // select the first "truthy" of these
Cortocircuito para llamar a una función opcional
El operador &&
se puede usar para evaluar una devolución de llamada, solo si se pasa:
function myMethod(cb) {
// This can be simplified
if (cb) {
cb();
}
// To this
cb && cb();
}
Por supuesto, la prueba anterior no valida que cb
sea en realidad una function
y no solo un Object
/ Array
/ String
/ Number
.
Resumen igualdad / desigualdad y conversión de tipos
El problema
Los operadores abstractos de igualdad y desigualdad ( ==
y !=
) Convierten sus operandos si los tipos de operandos no coinciden. Este tipo de coerción es una fuente común de confusión sobre los resultados de estos operadores, en particular, estos operadores no siempre son transitivos como se podría esperar.
"" == 0; // true A
0 == "0"; // true A
"" == "0"; // false B
false == 0; // true
false == "0"; // true
"" != 0; // false A
0 != "0"; // false A
"" != "0"; // true B
false != 0; // false
false != "0"; // false
Los resultados comienzan a tener sentido si considera cómo JavaScript convierte las cadenas vacías en números.
Number(""); // 0
Number("0"); // 0
Number(false); // 0
La solución
En la declaración false B
, ambos operandos son cadenas ( ""
y "0"
), por lo tanto no habrá conversión de tipos y como ""
y "0"
no tienen el mismo valor, "" == "0"
es false
como se esperaba.
Una forma de eliminar el comportamiento inesperado aquí es asegurarse de que siempre compare operandos del mismo tipo. Por ejemplo, si desea que los resultados de la comparación numérica use conversión explícita:
var test = (a,b) => Number(a) == Number(b);
test("", 0); // true;
test("0", 0); // true
test("", "0"); // true;
test("abc", "abc"); // false as operands are not numbers
O, si quieres comparación de cadenas:
var test = (a,b) => String(a) == String(b);
test("", 0); // false;
test("0", 0); // true
test("", "0"); // false;
Nota al margen : ¡El Number("0")
y el new Number("0")
no son lo mismo! Mientras que el primero realiza una conversión de tipo, el segundo creará un nuevo objeto. Los objetos se comparan por referencia y no por valor, lo que explica los resultados a continuación.
Number("0") == Number("0"); // true;
new Number("0") == new Number("0"); // false
Finalmente, tiene la opción de utilizar operadores de igualdad y desigualdad estrictos que no realizarán conversiones de tipo implícitas.
"" === 0; // false
0 === "0"; // false
"" === "0"; // false
Más referencia a este tema se puede encontrar aquí:
¿Qué operador igual (== vs ===) se debe usar en las comparaciones de JavaScript? .
Matriz vacía
/* ToNumber(ToPrimitive([])) == ToNumber(false) */
[] == false; // true
Cuando se ejecuta [].toString()
, llama a [].join()
si existe, o Object.prototype.toString()
contrario. Esta comparación devuelve true
porque [].join()
devuelve ''
que, forzado en 0
, es igual a fallar ToNumber .
Sin embargo, tenga cuidado, todos los objetos son sinceros y Array
es una instancia de Object
:
// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy'
[] ? 'truthy' : 'falsy'; // 'truthy'
Operaciones de comparación de igualdad
JavaScript tiene cuatro operaciones de comparación de igualdad diferentes.
SameValue
Devuelve true
si ambos operandos pertenecen al mismo Tipo y tienen el mismo valor.
Nota: el valor de un objeto es una referencia.
Puede utilizar este algoritmo de comparación a través de Object.is
(ECMAScript 6).
Ejemplos:
Object.is(1, 1); // true
Object.is(+0, -0); // false
Object.is(NaN, NaN); // true
Object.is(true, "true"); // false
Object.is(false, 0); // false
Object.is(null, undefined); // false
Object.is(1, "1"); // false
Object.is([], []); // false
Este algoritmo tiene las propiedades de una relación de equivalencia :
- Reflexividad :
Object.is(x, x)
estrue
, para cualquier valorx
- Simetría :
Object.is(x, y)
estrue
si, y solo si,Object.is(y, x)
estrue
, para cualquier valor dex
ey
. - Transitividad : si
Object.is(x, y)
yObject.is(y, z)
sontrue
,Object.is(x, z)
también estrue
, para cualquier valor dex
,y
yz
.
SameValueZero
Se comporta como SameValue, pero considera que +0
y -0
son iguales.
Puede usar este algoritmo de comparación a través de Array.prototype.includes
(ECMAScript 7).
Ejemplos:
[1].includes(1); // true
[+0].includes(-0); // true
[NaN].includes(NaN); // true
[true].includes("true"); // false
[false].includes(0); // false
[1].includes("1"); // false
[null].includes(undefined); // false
[[]].includes([]); // false
Este algoritmo todavía tiene las propiedades de una relación de equivalencia :
- Reflexividad :
[x].includes(x)
estrue
, para cualquier valorx
- Simetría :
[x].includes(y)
estrue
si, y solo si,[y].includes(x)
estrue
, para cualquier valor dex
ey
. - Transitividad : si
[x].includes(y)
y[y].includes(z)
sontrue
, entonces[x].includes(z)
también estrue
, para cualquier valor dex
,y
,y
z
.
Comparación de igualdad estricta
Se comporta como SameValue, pero
- Considera que
+0
y-0
son iguales. - Considera
NaN
diferente a cualquier valor, incluyéndose a sí mismo.
Puede utilizar este algoritmo de comparación a través del operador ===
(ECMAScript 3).
También está el operador !==
(ECMAScript 3), que niega el resultado de ===
.
Ejemplos:
1 === 1; // true
+0 === -0; // true
NaN === NaN; // false
true === "true"; // false
false === 0; // false
1 === "1"; // false
null === undefined; // false
[] === []; // false
Este algoritmo tiene las siguientes propiedades:
- Simetría :
x === y
estrue
si, y solo si, y === xis
verdadero, for any values
xand
y`. - Transitividad : si
x === y
yy === z
sontrue
, entoncesx === z
también estrue
, para cualquier valorx
,y
,y
z
.
Pero no es una relación de equivalencia porque
-
NaN
no es reflexivo :NaN !== NaN
Comparación de igualdad abstracta
Si ambos operandos pertenecen al mismo tipo, se comporta como la comparación de igualdad estricta.
De lo contrario, los obliga a lo siguiente:
-
undefined
ynull
se consideran iguales - Cuando se compara un número con una cadena, la cadena se convierte en un número
- Cuando se compara un booleano con otra cosa, el booleano se fuerza a un número
- Cuando se compara un objeto con un número, una cadena o un símbolo, el objeto es obligado a un primitivo
Si hubo una coerción, los valores coercitivos se comparan recursivamente. De lo contrario, el algoritmo devuelve false
.
Puede utilizar este algoritmo de comparación a través del operador ==
(ECMAScript 1).
También está el operador !=
(ECMAScript 1), que niega el resultado de ==
.
Ejemplos:
1 == 1; // true
+0 == -0; // true
NaN == NaN; // false
true == "true"; // false
false == 0; // true
1 == "1"; // true
null == undefined; // true
[] == []; // false
Este algoritmo tiene la siguiente propiedad:
- Simetría :
x == y
estrue
si, y solo si,y == x
estrue
, para cualquier valorx
ey
.
Pero no es una relación de equivalencia porque
-
NaN
no es reflexivo :NaN != NaN
- La transitividad no se mantiene, por ejemplo,
0 == ''
y0 == '0'
, pero'' != '0'
Agrupando múltiples declaraciones lógicas
Puede agrupar varias declaraciones lógicas booleanas entre paréntesis para crear una evaluación lógica más compleja, especialmente útil en declaraciones if.
if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) {
console.log('You can enter our club');
}
También podríamos mover la lógica agrupada a variables para hacer la declaración un poco más corta y descriptiva:
var isLegal = age >= 18;
var tall = height >= 5.11;
var suitable = isLegal && tall;
var isRoyalty = status === 'royalty';
var specialCase = isRoyalty && hasInvitation;
var canEnterOurBar = suitable || specialCase;
if (canEnterOurBar) console.log('You can enter our club');
Tenga en cuenta que en este ejemplo particular (y en muchos otros), agrupar las declaraciones con paréntesis funciona igual que si las elimináramos, simplemente siga una evaluación de lógica lineal y se encontrará con el mismo resultado. Prefiero usar paréntesis ya que me permite entender más claramente lo que pretendía y podría evitar errores lógicos.
Conversiones automáticas de tipos
Tenga en cuenta que los números pueden convertirse accidentalmente a cadenas o NaN (no es un número).
JavaScript está escrito a la ligera. Una variable puede contener diferentes tipos de datos, y una variable puede cambiar su tipo de datos:
var x = "Hello"; // typeof x is a string
x = 5; // changes typeof x to a number
Al realizar operaciones matemáticas, JavaScript puede convertir números en cadenas:
var x = 5 + 7; // x.valueOf() is 12, typeof x is a number
var x = 5 + "7"; // x.valueOf() is 57, typeof x is a string
var x = "5" + 7; // x.valueOf() is 57, typeof x is a string
var x = 5 - 7; // x.valueOf() is -2, typeof x is a number
var x = 5 - "7"; // x.valueOf() is -2, typeof x is a number
var x = "5" - 7; // x.valueOf() is -2, typeof x is a number
var x = 5 - "x"; // x.valueOf() is NaN, typeof x is a number
Restar una cadena de una cadena, no genera un error pero devuelve NaN (no es un número):
"Hello" - "Dolly" // returns NaN
Lista de operadores de comparación
Operador | Comparación | Ejemplo |
---|---|---|
== | Igual | i == 0 |
=== | Igual valor y tipo | i === "5" |
!= | No es igual | i != 5 |
!== | No igual valor o tipo | i !== 5 |
> | Mas grande que | i > 5 |
< | Menos que | i < 5 |
>= | Mayor que o igual | i >= 5 |
<= | Menor o igual | i <= 5 |
Campos de bits para optimizar la comparación de datos de múltiples estados
Un campo de bits es una variable que contiene varios estados booleanos como bits individuales. Un poco encendido representaría verdadero, y apagado sería falso. En el pasado, los campos de bits se usaban de forma rutinaria ya que guardaban memoria y reducían la carga de procesamiento. Aunque la necesidad de utilizar el campo de bits ya no es tan importante, sí ofrecen algunos beneficios que pueden simplificar muchas tareas de procesamiento.
Por ejemplo, la entrada del usuario. Al obtener información de las teclas de dirección de un teclado arriba, abajo, izquierda, derecha, puede codificar las distintas teclas en una sola variable con cada dirección asignada un bit.
Ejemplo de teclado de lectura a través de campo de bits
var bitField = 0; // the value to hold the bits
const KEY_BITS = [4,1,8,2]; // left up right down
const KEY_MASKS = [0b1011,0b1110,0b0111,0b1101]; // left up right down
window.onkeydown = window.onkeyup = function (e) {
if(e.keyCode >= 37 && e.keyCode <41){
if(e.type === "keydown"){
bitField |= KEY_BITS[e.keyCode - 37];
}else{
bitField &= KEY_MASKS[e.keyCode - 37];
}
}
}
Ejemplo de lectura como una matriz
var directionState = [false,false,false,false];
window.onkeydown = window.onkeyup = function (e) {
if(e.keyCode >= 37 && e.keyCode <41){
directionState[e.keyCode - 37] = e.type === "keydown";
}
}
Para activar un bit use bitwise o |
y el valor correspondiente al bit. Por lo tanto, si desea establecer el segundo bit, bitField |= 0b10
activará. Si desea desactivar un bit, use bitwise y &
con un valor que tenga todo por el bit requerido activado. Utilizando 4 bits y desactivando el segundo bit del bitfield &= 0b1101;
de bitfield &= 0b1101;
Puede decir que el ejemplo anterior parece mucho más complejo que asignar los diversos estados clave a una matriz. Sí. Es un poco más complejo de establecer, pero la ventaja viene al interrogar al estado.
Si quieres probar si todas las teclas están arriba.
// as bit field
if(!bitfield) // no keys are on
// as array test each item in array
if(!(directionState[0] && directionState[1] && directionState[2] && directionState[3])){
Puedes configurar algunas constantes para facilitar las cosas.
// postfix U,D,L,R for Up down left right
const KEY_U = 1;
const KEY_D = 2;
const KEY_L = 4;
const KEY_R = 8;
const KEY_UL = KEY_U + KEY_L; // up left
const KEY_UR = KEY_U + KEY_R; // up Right
const KEY_DL = KEY_D + KEY_L; // down left
const KEY_DR = KEY_D + KEY_R; // down right
A continuación, puede probar rápidamente varios estados de teclado diferentes
if ((bitfield & KEY_UL) === KEY_UL) { // is UP and LEFT only down
if (bitfield & KEY_UL) { // is Up left down
if ((bitfield & KEY_U) === KEY_U) { // is Up only down
if (bitfield & KEY_U) { // is Up down (any other key may be down)
if (!(bitfield & KEY_U)) { // is Up up (any other key may be down)
if (!bitfield ) { // no keys are down
if (bitfield ) { // any one or more keys are down
La entrada del teclado es solo un ejemplo. Los campos de bits son útiles cuando tiene varios estados en los que se debe actuar en combinación. Javascript puede usar hasta 32 bits para un campo de bits. Su uso puede ofrecer aumentos significativos de rendimiento. Vale la pena estar familiarizados con ellos.