Sök…
Anmärkningar
Vid användning av booleskt tvång betraktas följande värden "falskt" :
-
false
-
0
-
""
(tom sträng) -
null
-
undefined
-
NaN
(inte ett nummer, t.ex.0/0
) -
document.all
¹ (webbläsarsammanhang)
Allt annat betraktas som "sanningen" .
Logikoperatörer med booléer
var x = true,
y = false;
OCH
Denna operatör kommer att returnera sant om båda uttryck utvärderas till sant. Denna booleska operatör kommer att använda kortslutning och kommer inte att utvärdera y
om x
utvärderas till false
.
x && y;
Detta kommer att returnera falskt, eftersom y
är falskt.
ELLER
Denna operatör kommer att returnera sant om ett av de två uttryck utvärderar till sant. Denna booleska operatör kommer att använda kortslutning och y
kommer inte att utvärderas om x
utvärderas till true
.
x || y;
Detta kommer att återkomma, eftersom x
är sant.
INTE
Denna operatör kommer att returnera falskt om uttrycket till höger utvärderar till sant, och returnerar sant om uttrycket till höger utvärderar till falskt.
!x;
Detta kommer att returnera falskt, eftersom x
är sant.
Abstrakt jämställdhet (==)
Operanterna för operatören för abstrakt jämlikhet jämförs efter att de har konverterats till en vanlig typ. Hur denna konvertering sker baseras på specifikationen för operatören:
Specifikation för operatören ==
:
7.2.13 Abstrakt jämställdhetsjämförelse
Jämförelsenx == y
, därx
ochy
är värden, gertrue
ellerfalse
. En sådan jämförelse utförs enligt följande:
- Om
Type(x)
är samma somType(y)
, gör så:
- a. Returnera resultatet av att utföra Strict Equality Comparison
x === y
.
- Om
x
ärnull
ochy
ärundefined
, returneratrue
.- Om
x
ärundefined
ochy
ärnull
, returneratrue
.- Om
Type(x)
ärNumber
ochType(y)
ärString
, returnerar resultatet av jämförelsenx == ToNumber(y)
.- Om
Type(x)
ärString
ochType(y)
ärNumber
, returnera resultatet av jämförelsenToNumber(x) == y
.- Om
Type(x)
ärBoolean
, returnerar du resultatet av jämförelsenToNumber(x) == y
.- Om
Type(y)
ärBoolean
, returnerar du resultatet avcomparison x == ToNumber(y)
.- Om
Type(x)
antingen ärString
,Number
ellerSymbol
ochType(y)
ärObject
, returnerar resultatet av jämförelsenx == ToPrimitive(y)
.- Om
Type(x)
är Objekt ochType(y)
är antingenString
,Number
ellerSymbol
, returnerar resultatet av jämförelsenToPrimitive(x) == y
.- Returnera
false
.
Exempel:
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
Relationsoperatörer (<, <=,>,> =)
När båda operanderna är numeriska jämförs de normalt:
1 < 2 // true
2 <= 2 // true
3 >= 5 // false
true < false // false (implicitly converted to numbers, 1 > 0)
När båda operanderna är strängar jämförs de lexikografiskt (enligt alfabetisk ordning):
'a' < 'b' // true
'1' < '2' // true
'100' > '12' // false ('100' is less than '12' lexicographically!)
När en operand är en sträng och den andra är ett nummer konverteras strängen till ett nummer före jämförelse:
'1' < 2 // true
'3' > 2 // true
true > '2' // false (true implicitly converted to number, 1 < 2)
När strängen är icke-numerisk, returnerar numerisk konvertering NaN
(inte-ett-nummer). Jämförelse med NaN
returnerar alltid false
:
1 < 'abc' // false
1 > 'abc' // false
Men var försiktig när du jämför ett numeriskt värde med null
, undefined
eller tomma strängar:
1 > '' // true
1 < '' // false
1 > null // true
1 < null // false
1 > undefined // false
1 < undefined // false
När en operand är ett objekt och den andra är ett nummer konverteras objektet till ett nummer före jämförelse. null
är särskilt fall eftersom Number(null);//0
new Date(2015)< 1479480185280 // true
null > -1 //true
({toString:function(){return 123}}) > 122 //true
Olikhet
Operatör !=
Är invers från operatören ==
.
Kommer tillbaka true
om operanderna är inte lika.
Javascript-motorn kommer att försöka konvertera båda operanderna till matchande typer om de inte är av samma typ. Obs: Om de två operandema har olika interna referenser i minnet, kommer false
att returneras.
Prov:
1 != '1' // false
1 != 2 // true
I exemplet ovan är 1 != '1'
false
eftersom en primitiv siffertyp jämförs med ett char
värde. Därför bryr inte Javascript-motorn sig om datatypen för RHS-värdet.
Operatör !==
är invers från operatören ===
. Kommer tillbaka om operandarna inte är lika eller om deras typer inte matchar.
Exempel:
1 !== '1' // true
1 !== 2 // true
1 !== 1 // false
Logikoperatörer med icke-booleska värden (booleskt tvång)
Logiskt ELLER ( ||
), som läser från vänster till höger, kommer att utvärdera till det första sanningsvärdet . Om inget sanningsvärde hittas returneras det sista värdet.
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'
Logiskt OCH ( &&
), läsning från vänster till höger, kommer att utvärdera till det första falska värdet. Om inget falsey- värde hittas, returneras det sista värdet.
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
Detta trick kan till exempel användas för att ställa in ett standardvärde till ett funktionsargument (före 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
Tänk bara på att för argument, 0
och (i mindre utsträckning) är den tomma strängen ofta giltiga värden som borde kunna passeras uttryckligen och åsidosätta ett standard, som de med detta mönster inte kommer att göra (eftersom de är falsk ).
Null och odefinierad
Skillnaderna mellan null
och undefined
null
och undefined
dela abstrakt jämlikhet ==
men inte strikt jämlikhet ===
,
null == undefined // true
null === undefined // false
De representerar något olika saker:
-
undefined
representerar frånvaron av ett värde , till exempel innan en identifierare / Objektegenskap har skapats eller under perioden mellan skapande av identifierare / Funktionsparametrar och dess första inställning, om någon. -
null
representerar avsiktlig frånvaro av ett värde för en identifierare eller egendom som redan har skapats.
De är olika typer av syntax:
-
undefined
är en egenskap hos det globala objektet , vanligtvis oföränderligt i det globala omfånget. Detta betyder att var som helst du kan definiera att en annan identifierare än i det globala namnområdet kan döljaundefined
från det räckvidden (även om saker fortfarande kanundefined
) -
null
är ett ord bokstavligt , så det innebär att det aldrig kan ändras och att försöka göra det kommer att kasta ett fel .
Likheterna mellan null
och undefined
null
och undefined
är båda falska.
if (null) console.log("won't be logged");
if (undefined) console.log("won't be logged");
Varken null
eller undefined
lika false
(se denna fråga ).
false == undefined // false
false == null // false
false === undefined // false
false === null // false
Använda undefined
- Om det nuvarande räckvidden inte kan lita på, använd något som utvärderar till odefinierat , till exempel
void 0;
. - Om
undefined
är skuggad av ett annat värde, är det lika dåligt som att skuggaArray
ellerNumber
. - Undvik att ställa in något som
undefined
. Om du vill ta bort en fastighet bar från ett objektfoo
,delete foo.bar;
istället. - Existentest-identifierare
foo
motundefined
kan kasta ett referensfel , användtypeof foo
mot"undefined"
istället.
Det globala objektets NaN-egendom
NaN
(" N ot a N umber") är ett specialvärde som definieras av IEEE-standarden för flytande punkt aritmetik , som används när ett icke-numeriskt värde tillhandahålls men ett tal förväntas ( 1 * "two"
), eller när en beräkning inte har ett giltigt number
resultat ( Math.sqrt(-1)
).
Varje jämlikhet eller relationella jämförelser med NaN
returnerar false
, till och med att jämföra det med sig själv. Eftersom NaN
är tänkt att beteckna resultatet av en nonsensical beräkning, och som sådan är det inte lika med resultatet av andra nonsensical beräkningar.
(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
Icke-lika jämförelser kommer alltid att true
:
NaN !== 0; // true
NaN !== NaN; // true
Kontrollera om ett värde är NaN
Du kan testa ett värde eller ett uttryck för NaN
med hjälp av funktionen 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
Du kan kontrollera om ett värde är NaN
genom att jämföra det med sig själv:
value !== value; // true for NaN, false for any other value
Du kan använda följande polyfill för Number.isNaN()
:
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
Däremot den globala funktionen isNaN()
returnerar true
inte bara för NaN
, utan även för något värde eller uttryck som inte kan tvingas in i ett antal:
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 definierar en "likhet" SameValue
som heter SameValue
som sedan ECMAScript 6 kan åberopas med Object.is
. Till skillnad ===
jämförelsen ==
och ===
, kommer Object.is()
att behandla NaN
som identisk med sig själv (och -0
som inte identisk med +0
):
Object.is(NaN, NaN) // true
Object.is(+0, 0) // false
NaN === NaN // false
+0 === 0 // true
Du kan använda följande polyfill för Object.is()
(från 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;
}
};
}
Poäng att notera
NaN själv är ett tal, vilket betyder att det inte är lika med strängen "NaN", och viktigast av allt (men kanske oinitivt):
typeof(NaN) === "number"; //true
Kortslutning hos booleska operatörer
Operatören ( &&
) och operatören ( ||
) använder kortslutning för att förhindra onödigt arbete om resultatet av operationen inte förändras med extraarbetet.
I x && y
kommer y
inte att utvärderas om x
utvärderas till false
, eftersom hela uttrycket garanteras vara false
.
I x || y
, y
kommer inte att utvärderas om x
utvärderas till true
, eftersom hela uttrycket garanteras vara true
.
Exempel med funktioner
Ta följande två funktioner:
function T() { // True
console.log("T");
return true;
}
function F() { // False
console.log("F");
return false;
}
Exempel 1
T() && F(); // false
Produktion:
'T'
'F'
Exempel 2
F() && T(); // false
Produktion:
'F'
Exempel 3
T() || F(); // true
Produktion:
'T'
Exempel 4
F() || T(); // true
Produktion:
'F'
'T'
Kortslutning för att förhindra fel
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
Rad A: om du vänder ordningen kommer det första villkorade uttalandet att förhindra felet på det andra genom att inte utföra det om det skulle kasta felet
if(obj !== undefined && obj.property){}; // no error thrown
Men bör endast användas om du förväntar dig undefined
if(typeof obj === "object" && obj.property){}; // safe option but slower
Kortslutning för att ge ett standardvärde
Den ||
operatören kan användas för att välja antingen ett "sanningsvärde" eller standardvärdet.
Till exempel kan detta användas för att säkerställa att ett nullable värde konverteras till ett icke nullable värde:
var nullableObj = null;
var obj = nullableObj || {}; // this selects {}
var nullableObj2 = {x: 5};
var obj2 = nullableObj2 || {} // this selects {x: 5}
Eller för att returnera det första sanningsvärdet
var truthyValue = {x: 10};
return truthyValue || {}; // will return {x: 10}
Samma kan användas för att falla tillbaka flera gånger:
envVariable || configValue || defaultConstValue // select the first "truthy" of these
Kortslutning för att ringa en valfri funktion
Operatören &&
kan användas för att utvärdera ett återuppringning, bara om det skickas:
function myMethod(cb) {
// This can be simplified
if (cb) {
cb();
}
// To this
cb && cb();
}
Naturligtvis validerar testet ovan inte att cb
faktiskt är en function
och inte bara ett Object
/ Array
/ String
/ Number
.
Abstrakt jämlikhet / ojämlikhet och typkonvertering
Problemet
Operatörerna för abstrakt jämlikhet och ojämlikhet ( ==
och !=
) Konverterar sina operander om operandtyperna inte matchar. Denna typ av tvång är en vanlig källa till förvirring kring resultaten från dessa operatörer, särskilt dessa operatörer är inte alltid övergående som man kan förvänta sig.
"" == 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
Resultaten börjar vara meningsfulla om du funderar på hur JavaScript konverterar tomma strängar till siffror.
Number(""); // 0
Number("0"); // 0
Number(false); // 0
Lösningen
I uttalandet false B
är båda operanderna strängar ( ""
och "0"
), därför kommer det inte att finnas någon typkonvertering och eftersom ""
och "0"
inte är samma värde, "" == "0"
är false
som förväntat.
Ett sätt att eliminera oväntat beteende här är att se till att du alltid jämför operander av samma typ. Om du till exempel vill ha resultat från numerisk jämförelse använder du explicerad konvertering:
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
Eller om du vill jämföra sträng:
var test = (a,b) => String(a) == String(b);
test("", 0); // false;
test("0", 0); // true
test("", "0"); // false;
Sidnot : Number("0")
och new Number("0")
är inte samma sak! Medan den förstnämnda utför en typkonvertering kommer den senare att skapa ett nytt objekt. Objekt jämförs med referens och inte med värde vilket förklarar resultaten nedan.
Number("0") == Number("0"); // true;
new Number("0") == new Number("0"); // false
Slutligen har du möjlighet att använda strikta jämställdhets- och ojämlikhetsoperatörer som inte kommer att utföra några implicita typkonverteringar.
"" === 0; // false
0 === "0"; // false
"" === "0"; // false
Mer information om detta ämne finns här:
Vilka är lika med operatören (== vs ===) som ska användas i JavaScript-jämförelser? .
Tom Array
/* ToNumber(ToPrimitive([])) == ToNumber(false) */
[] == false; // true
När [].toString()
körs ringer det [].join()
om det finns, eller Object.prototype.toString()
annars. Denna jämförelse återgår true
eftersom [].join()
returnerar ''
som tvingas till 0
är lika med falskt ToNumber .
Akta dig dock, alla objekt är sanningsenliga och Array
är ett exempel på Object
:
// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy'
[] ? 'truthy' : 'falsy'; // 'truthy'
Jämställdhetsjämförelse
JavaScript har fyra olika jämställdhetsjämförelser.
SameValue
Det returnerar true
om båda operanderna tillhör samma typ och har samma värde.
Obs: värdet på ett objekt är en referens.
Du kan använda denna jämförelsealgoritm via Object.is
(ECMAScript 6).
Exempel:
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
Denna algoritm har egenskaperna för en ekvivalensrelation :
- Reflexivitet :
Object.is(x, x)
ärtrue
, för alla värdenx
- Symmetri :
Object.is(x, y)
ärtrue
om, och endast omObject.is(y, x)
ärtrue
, för alla värdenx
ochy
. - Transitivitet : Om
Object.is(x, y)
ochObject.is(y, z)
ärtrue
, ärObject.is(x, z)
ocksåtrue
, för alla värdenx
,y
ochz
.
SameValueZero
Det uppför sig som SameValue, men anser att +0
och -0
är lika.
Du kan använda denna jämförelsealgoritm via Array.prototype.includes
(ECMAScript 7).
Exempel:
[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
Denna algoritm har fortfarande egenskaperna för en ekvivalensrelation :
- Reflexivitet :
[x].includes(x)
ärtrue
, för alla värdenx
- Symmetri :
[x].includes(y)
ärtrue
om, och endast om,[y].includes(x)
ärtrue
, för alla värdenx
ochy
. - Transitivitet : Om
[x].includes(y)
och[y].includes(z)
ärtrue
, är[x].includes(z)
ocksåtrue
, för alla värdenx
,y
ochz
.
Strikt jämställdhetsjämförelse
Det uppför sig som SameValue, men
- Anser att
+0
och-0
ska vara lika. - Anser att
NaN
annorlunda än något värde, inklusive sig själv
Du kan använda denna jämförelsealgoritm via ===
operatören (ECMAScript 3).
Det finns också !==
operatören (ECMAScript 3), som förnekar resultatet av ===
.
Exempel:
1 === 1; // true
+0 === -0; // true
NaN === NaN; // false
true === "true"; // false
false === 0; // false
1 === "1"; // false
null === undefined; // false
[] === []; // false
Denna algoritm har följande egenskaper:
- Symmetri :
x === y
ärtrue
om, och bara om, y === xis
sant, for any values
xand
y`. - Transitivitet : Om
x === y
ochy === z
ärtrue
, ärx === z
ocksåtrue
, för alla värdenx
,y
ochz
.
Men är inte en ekvivalensrelation för
-
NaN
är inte reflexivt :NaN !== NaN
Abstrakt jämställdhetsjämförelse
Om båda operanderna tillhör samma typ, uppträder det som Strict Equality Comparison.
Annars tvingar det dem enligt följande:
-
undefined
ochnull
anses vara lika - När man jämför ett nummer med en sträng, tvingas strängen till ett nummer
- När man jämför en boolean med något annat, tvingas den boolesiska till ett tal
- När man jämför ett objekt med ett nummer, sträng eller symbol tvingas objektet till en primitiv
Om det var tvång, jämförs de tvingade värdena rekursivt. Annars returnerar algoritmen false
.
Du kan använda denna jämförelsealgoritm via ==
operatören (ECMAScript 1).
Det finns också !=
Operatören (ECMAScript 1), som förnekar resultatet av ==
.
Exempel:
1 == 1; // true
+0 == -0; // true
NaN == NaN; // false
true == "true"; // false
false == 0; // true
1 == "1"; // true
null == undefined; // true
[] == []; // false
Denna algoritm har följande egenskap:
- Symmetri :
x == y
ärtrue
om, och bara om,y == x
ärtrue
, för alla värdenx
ochy
.
Men är inte en ekvivalensrelation för
-
NaN
är inte reflexivt :NaN != NaN
- Transitivitet rymmer inte, t.ex.
0 == ''
och0 == '0'
, men'' != '0'
Gruppera flera logiska uttalanden
Du kan gruppera flera booleska logiska uttalanden inom parentes för att skapa en mer komplex logisk utvärdering, särskilt användbar om uttalanden.
if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) {
console.log('You can enter our club');
}
Vi kan också flytta den grupperade logiken till variabler för att göra uttalandet lite kortare och beskrivande:
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');
Lägg märke till att i det här exemplet (och många andra), gruppering av uttalanden med parentes fungerar på samma sätt som om vi tog bort dem, följ bara en linjär logisk utvärdering så hittar du dig själv med samma resultat. Jag föredrar att använda parenteser eftersom det gör att jag kan förstå tydligare vad jag tänkte och kan förhindra för logiska misstag.
Automatiska typkonverteringar
Se upp för att oavsiktligt kan konverteras till strängar eller NaN (Inte ett nummer).
JavaScript skrivs löst. En variabel kan innehålla olika datatyper och en variabel kan ändra dess datatyp:
var x = "Hello"; // typeof x is a string
x = 5; // changes typeof x to a number
När du gör matematiska operationer kan JavaScript konvertera nummer till strängar:
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
Att subtrahera en sträng från en sträng genererar inte ett fel utan returnerar NaN (inte ett nummer):
"Hello" - "Dolly" // returns NaN
Lista över jämförande operatörer
Operatör | Jämförelse | Exempel |
---|---|---|
== | Likvärdig | i == 0 |
=== | Lika värde och typ | i === "5" |
!= | Inte jämnlikt | i != 5 |
!== | Inte lika värde eller typ | i !== 5 |
> | Större än | i > 5 |
< | Mindre än | i < 5 |
>= | Större än eller lika med | i >= 5 |
<= | Mindre än eller lika | i <= 5 |
Bitfält för att optimera jämförelsen av multi-state-data
Ett bitfält är en variabel som innehåller olika booleska tillstånd som enskilda bitar. Lite på skulle representera sant och av skulle vara falskt. Tidigare användes bitfält rutinmässigt eftersom de sparade minne och minskade behandlingsbelastning. Även om behovet av att använda bitfält inte längre är så viktigt erbjuder de vissa fördelar som kan förenkla många behandlingsuppgifter.
Till exempel användarinmatning. När du får input från ett tangentbords riktningstangenter upp, ner, vänster, höger kan du koda de olika tangenterna till en enda variabel med varje riktning tilldelad en bit.
Exempel på läsningstangentbord via bitfält
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];
}
}
}
Exempelläsning som en matris
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";
}
}
För att slå på lite använder du bitvis eller |
och värdet som motsvarar biten. Så om du vill ställa in den andra biten bitField |= 0b10
slår den på. Om du vill stänga av lite använder du bitvis och &
med ett värde som har alla med den önskade biten på. Använda 4 bitar och stänga av den andra biten från bitfield &= 0b1101;
Du kan säga att exemplet ovan verkar mycket mer komplicerat än att tilldela olika nyckeltillstånd till en matris. Ja Det är lite mer komplicerat att ställa in, men fördelen kommer när man förhör staten.
Om du vill testa om alla knappar är uppe.
// 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])){
Du kan ställa in några konstanter för att göra det lättare
// 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
Du kan sedan snabbt testa för många olika tangentbordstillstånd
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
Tangentbordets ingång är bara ett exempel. Bitfält är användbara när du har olika tillstånd som måste kombineras. Javascript kan använda upp till 32 bitar för ett bitfält. Att använda dem kan ge betydande prestationsökningar. De är värda att vara bekanta med.