Under hela denna serie artiklar har vi pratat om tvångstyp, hur det skiljer sig från typkonvertering och hur det fungerar på dynamiskt typade språk.
Om du bara går med i serien, kolla in de tidigare artiklarna för att se till att du är snabb med var vi är just nu:
Den andra artikeln fokuserade på svagt typade språk och datatyper på en hög nivå. Vi ska titta på några specifika exempel på tvångstyp på ett svagt typat språk och de fallgropar som vi kan uppleva utan att veta hur typen tvång fungerar och hur det kan komma tillbaka.
Specifikt kommer vi att titta på flera exempel med JavaScript, och även om resultaten som du kan se genom användningen av exemplen inte nödvändigtvis översätter 1: 1 på andra språk, kommer det fortfarande att ge en uppsättning test som du kan utföra i vad som helst du använder i din dagliga eller i din sida projekt och utvärdera resultaten som du ser.
Förmodligen kommer ett av de vanligaste problemen som uppstår på svagt typade språk när vi gör jämförelser. Visst finns det andra tider som förväntar sig att en variabel är en typ när det verkligen är ett annat kan negativt påverka oss, men de vanligaste problemen uppstår när vi utför någon typ av jämförelse.
Dessa jämförelser kan komma i form av likabehandling, villkorliga operationer, bitvisa operationer eller under switch fallet
operationer.
Som nämnts i tidigare artiklar i denna serie har olika språk olika sätt på vilka de handlar om tvingande datatyper, så de exempel vi tittar på i den här artikeln kan skilja sig lite från det arbete du gör.
Det vill säga vi ska titta på dessa exempel med hjälp av JavaScript eftersom det är ett så spritt språk, men reglerna är fortfarande tillämpliga på andra språk - det är bara att andra språk kan placera en annan prioritet på en datatyp än en annan så Resultaten av tvång kan vara lite annorlunda.
Så med det sagt, låt oss börja när vi tittar på hur JavaScript hanterar jämförelser mellan datatyper med likhetsoperatören (==
), den strikta jämställdhetsoperatören (===
), och när man använder värden som odefinierad
och null
.
Innan vi tittar på jämförelser mellan olika datatyper, låt oss ta en stund att notera det, i JavaScript, odefinierad
och null
är två olika typer av värden. Som om det inte räcker kan det bli ännu mer förvirrande när man jämför de två värdena.
Först notera följande:
typof (odefinierad)
i konsolen, då skulle resultatet bli odefinierad
.typof (null)
i konsolen, då skulle resultatet bli objekt
.Om du skulle förklara en variabel utan att faktiskt ange ett värde, och du skulle utvärdera sin typ så skulle du se odefinierad
.
/ ** * Förklara ett variabelt namn men inte tilldela det ett värde. * Utför resultatet av 'typof' på en konsol och du får * vara odefinierad. ' * / var namn; typof (namn);
Låt oss nu säga att vi väljer att initiera variabeln med en null
värde. Om du skulle utvärdera variabeln med sorts
du skulle få en objekt
resultat.
// Först ska vi deklarera variabelvarnumret; / ** * Om vi skulle utvärdera variabeln * använder typof så skulle vi få "odefinierad". * / // Nu tilldela variabeln ett värde av 'null'-nummer = null; / ** * Och utvärdera variabeln. Vid denna tidpunkt kommer vi * att returneras värdet av "objekt". * / typ av (antal);
Förvirrande? Minns från tidigare att det i JavaScript, null
är en objekt
där odefinierad är sin egen typ - odefinierad
.
Med det sagt kan vi nu faktiskt titta på varför jämförelser kan bli svåra när vi utför jämförelser på värden utan att uttryckligen veta deras typ.
Under hela det här avsnittet ska vi titta på resultaten av att jämföra värden som är av olika slag, men se hur de utvärderas mot varandra med hjälp av både jämlikhetsjämförelser och strikta jämlikhetsjämförelser.
Observera att alla exemplen som vi listar nedan ska kunna utföras i en webbläsares konsol, t.ex. Firebug eller Chrome Developer Tools.
Till att börja med börjar vi med odefinierad
och null
.
// Returnerar sant odefinierat == null; null == odefinierad; // Returnerar false undefined === null; null === odefinierad;
Observera att jämställdhetsoperatören i det första fallet returnerar ett värde av jämförelsen efter utför typtyngd. Det är, tolken gör sitt bästa gissning om vad vi menar när vi utför denna jämförelse.
I det andra fallet använder vi strikt likhetsoperatören. I detta fall inträffar ingen typ tvång. Istället tar det värden exakt som de är och jämför dem.
Låt oss då ta en titt på att deklarera en variabel, inte tilldela det ett värde och sedan köra en jämförelse.
// Förklara variabeln, inte tilldela det ett värde var exempel; // I jämförelse med odefinierad returnerar sant i båda fallen exemplet == odefinierat; exemplet === odefinierat // I jämförelse med null returneras sant eller felaktigt exempel == null; // sant exempel === null; // false // Tilldela ett värde till det variabla exemplet = null; // Gör nu ett strikt jämförelsesexempel === null; // Returnerar sant
Som du kan se börjar saker börjar bli lite mer komplicerade när vi börjar förklara och jämföra variabler med eller utan värden.
När vi börjar introducera strängar, siffror och boolesiska värden kan det bli ännu mer komplicerat. Låt oss börja med strängar och siffror. Vi börjar med att deklarera en variabel med ett strängvärde på 42
och ett nummer med 42
och då ska vi göra våra jämförelser.
var sNumber, iNumber; sNumber = '42'; iNumber = 42; // Jämlikhetsjämförelser ger sann sNumber == iNumber; // Strikt jämförelse ger falskt sNumber === iNumber;
Återigen, märka i det första fallet, försöker tolken att tvinga värdena från variablerna och sedan jämföra dem. I det första fallet fungerar det - vi jämför ett strängvärde av 42
till ett talvärde på 42
, men när vi använder den strikta jämlikhetsjämförelsen och får falsk
.
Det andra fallet är tekniskt noggrannare eftersom det första värdet är en sträng och den andra är ett tal. Att jämföra två värden av olika typer borde alltid ge falskt.
Även om vi har tittat på det här i en tidigare artikel, vad sägs om tal och booleaner?
var iNumber, bBoolean; iNumber = 0; bBoolean = false; // Returnerar sant iNumber == bBoolean; // Returnerar false iNumber === bBoolean; // Returnerar sant iNumber = 1; bBoolean = true; iNumber == bBoolean; // Returnerar false iNumber === bBoolean;
Vid denna tidpunkt bör du börja märka ett mönster: När du jämför värden av olika typer kan JavaScript på ett korrekt sätt tvinga värden, men det ger det mest exakta resultatet när du använder strikt likhetsoperatören.
Slutligen, låt oss titta på ett exempel som kombinerar strängar, nummer och booleaner.
var sExample, iExample, bExample; sExample = '1'; iExempel = 1; bExample = true; // Returnerar sant sExample == iExample; // Returnerar false sExample === iExample; // Returnerar sant iExample == bExample; // Returnerar false iExample === bExample; // Returnerar sant sExample == bExample; // Returnerar false sExample === bExample;
Observera att dessa är grundläggande jämförelser; men när det görs i samband med en om annat
eller om / annars om / annars
du ser hur det kan störa kontrollflödet genom det villkorliga.
Observera att när du utför logiska operationer, t.ex. &&
och ||
såväl som bitvis operatörer som &
och |
att tvångsreglerna fortfarande gäller. För det ändamålet vill du vara säker på att när du utför dessa operationer använder du värden av exakt samma typ för att få de mest exakta resultaten.
Annars kan tvång resultera i en falsk positiv eller en falsk negativ.
Detta avslutar vår översiktliga, nybörjarens titt på datatyper och skriver tvång på ett dynamiskt skrivet språk. I slutändan är tumreglerna alltid att använda strikta jämställdhetsoperatörer och se till att de variabler som du arbetar med är av samma typ. Om du inte är säker kan du alltid uttryckligen konvertera dem med hjälp av strategier som vi skisserade tidigare i serien.
Under hela serien har vi tittat på hur olika typer varierar och beter sig från starkt skrivna språk till svagt skrivna språk. Vi har tittat på hur gjutning och tvång skiljer sig åt, och vi har tittat på några av de potentiella fallgroparna som detta kan leda till att förlita sig på tolken eller kompilatorn vid jämförelser.
Slutligen tog vi en titt på några strategier för hur man skriver mer defensiv kod genom att se till att vi har den datatyp vi behöver och hur man använder strikta jämförelseoperatörer för att se till att vi får de resultat vi behöver.
Som tidigare nämnts har vi använt JavaScript för syftet med våra exempel i denna allvarliga artiklar, men andra svagt typade språk är föremål för samma fallgropar. Hur de prioriterar sina tvång varierar, men de strategier som skisseras i denna serie bör hjälpa till med att skriva mer eftergiven kod när de arbetar på svagt typade språk.