In deze reeks artikelen hebben we het gehad over type dwang, hoe deze verschilt van typeconversie en hoe deze presteert in dynamisch getypte talen.
Als je net meedoet met de serie, bekijk dan de eerdere artikelen om er zeker van te zijn dat je op de hoogte bent van waar we nu zijn:
Terwijl het andere artikel zich concentreerde op zwak getypte talen en gegevenstypes op een hoog niveau, zullen we enkele specifieke voorbeelden van type dwang in een zwak getypeerde taal bekijken, en de valkuilen die we kunnen ervaren zonder te weten hoe type dwang werkt en hoe het kan averechts werken.
Specifiek zullen we verschillende voorbeelden bekijken met behulp van JavaScript, en hoewel de uitkomsten die u mogelijk ziet door het gebruik van de voorbeelden, niet noodzakelijk 1: 1 in andere talen zullen vertalen, zal het nog steeds een reeks tests bieden die u kan presteren in wat u ook gebruikt in uw dagelijkse of in uw zijprojecten en de resultaten evalueren die u ziet.
Misschien is een van de meest voorkomende problemen die optreedt in zwak getypte talen, elke keer dat we vergelijkingen maken. Natuurlijk zijn er andere tijden waarbij een variabele één type is, terwijl de andere echt een negatief effect op ons kan hebben, maar de meest voorkomende problemen doen zich voor wanneer we een of andere vergelijking uitvoeren..
Deze vergelijkingen kunnen de vorm hebben van gelijkheidsbewerkingen, voorwaardelijke bewerkingen, bitsgewijze bewerkingen of tijdens switch / case
activiteiten.
Zoals vermeld in eerdere artikelen in deze serie, hebben verschillende talen verschillende manieren om datatypes te dwingen, zodat de voorbeelden die we in dit artikel behandelen enigszins kunnen verschillen in het werk dat u doet.
Dat wil zeggen dat we deze voorbeelden met behulp van JavaScript gaan bekijken, omdat het zo'n veelgebruikte taal is, maar de regels zijn nog steeds van toepassing in andere talen - het is alleen dat andere talen een andere prioriteit kunnen stellen op een gegevenstype dan een andere, dus de resultaten van dwang kunnen een beetje anders zijn.
Laten we daarom beginnen met kijken naar hoe JavaScript omgaat met vergelijkingen tussen gegevenstypen met behulp van de gelijkheidsoperator (==
), de strikte operator voor gelijkheid (===
) en bij het gebruik van waarden zoals onbepaald
en nul
.
Voordat we kijken naar vergelijkingen tussen verschillende gegevenstypen, nemen we even de tijd om op te merken dat in JavaScript, onbepaald
en nul
zijn twee verschillende soorten waarden. Alsof dat nog niet genoeg is, kan het zelfs nog verwarrender worden bij het vergelijken van de twee waarden.
Merk eerst het volgende op:
typeof (niet gedefinieerd)
in de console, dan zou het resultaat zijn onbepaald
.typeof (null)
in de console, dan zou het resultaat zijn voorwerp
.Als u vervolgens een variabele declareert zonder deze daadwerkelijk een waarde toe te wijzen, en u het type ervan zou evalueren, zou u zien onbepaald
.
/ ** * Declareer een variabele 'naam' maar wijs er geen waarde aan toe. * Voer het resultaat van 'typeof' uit op een console en u krijgt * undefined. * / var naam; typeof (naam);
Laten we vervolgens stellen dat we ervoor kiezen om de variabele te initialiseren met een nul
waarde. Als je de variabele zou evalueren met soort van
je zou een krijgen voorwerp
resultaat.
// Eerst zullen we het variabele var-nummer declareren; / ** * Als we op dit moment de variabele * zouden evalueren met behulp van typeof, zouden we 'undefined' worden gegeven. * / // Wijs nu de variabele een waarde toe van 'nul' nummer = null; / ** * En evalueer de variabele. Op dit punt krijgen we * de waarde van 'object' terug. * / typeof (nummer);
Verwarrend? Herinner van vroeger dat dat in JavaScript, nul
is een voorwerp
waar undefined zijn eigen type is - onbepaald
.
Met dat gezegd, nu kunnen we echt kijken waarom vergelijkingen moeilijk kunnen worden wanneer we vergelijkingen uitvoeren op waarden zonder expliciet het type te kennen.
In deze sectie gaan we de resultaten van het vergelijken van waarden van verschillende typen bekijken, maar kijken we hoe ze tegen elkaar worden geëvalueerd door zowel gelijkheidsvergelijkingen als strikte gelijkheidsvergelijkingen te gebruiken.
Houd er rekening mee dat alle onderstaande voorbeelden kunnen worden uitgevoerd in de consolebrowser van een browser, zoals Firebug of de ontwikkelaarstools van Chrome..
Om te beginnen beginnen we met onbepaald
en nul
.
// Retourneert true undefined == null; null == undefined; // Geeft false undefined === null; null === niet gedefinieerd;
Merk op dat in het eerste geval de gelijkheidsoperator een waarde van de vergelijking retourneert na het uitvoeren van type dwang. Dat wil zeggen dat de tolk zijn beste inschatting maakt van wat we bedoelen bij het uitvoeren van deze vergelijking.
In het tweede geval gebruiken we de operator voor strikte gelijkheid. In dit geval treedt geen type dwang op. In plaats daarvan worden de waarden precies zoals ze zijn en vergeleken ze.
Laten we vervolgens eens kijken naar het declareren van een variabele, er geen waarde aan toewijzen en vervolgens een vergelijking uitvoeren.
// Declareer de variabele, wijs er geen waarde var toe; // In vergelijking met undefined, geeft true als resultaat in beide gevallen == undefined; example === undefined // Indien vergeleken met null, geeft true of false example == null; // true example === null; // false // Wijs een waarde toe aan de variabele example = null; // Doe nu een strikt vergelijkingsvoorbeeld === null; // Retourneert waar
Zoals u kunt zien, begint het iets ingewikkelder te worden wanneer we beginnen met het verklaren en vergelijken van variabelen met of zonder waarden.
Zodra we beginnen met het introduceren van tekenreeksen, getallen en booleaanse waarden, kan het nog ingewikkelder worden. Laten we eerst beginnen met strings en cijfers. We beginnen met het declareren van een variabele met een tekenreekswaarde van 42
en een nummer met de 42
en dan zullen we onze vergelijkingen uitvoeren.
var sNumber, iNumber; sNumber = '42'; iNummer = 42; // Gelijkheidsvergelijkingen geven waar sNumber == iNumber; // Strikte vergelijking levert false op sNumber === iNumber;
Nogmaals, let op in het eerste geval probeert de interpreter de waarden uit de variabelen te dwingen en ze vervolgens te vergelijken. In het eerste geval werkt het - we vergelijken een tekenreekswaarde van 42
naar een getalswaarde van 42
, maar wanneer we de strikte gelijkheidsvergelijking gebruiken en krijgen vals
.
Het tweede geval is technisch nauwkeuriger omdat de eerste waarde een tekenreeks is en de tweede een getal. Het vergelijken van twee waarden van verschillende typen zou altijd vals moeten zijn.
Hoewel we dit in een vorig artikel hebben bekeken, hoe zit het met het geval van nummers en booleans?
var iNumber, bBoolean; iNummer = 0; bBoolean = false; // Retourneert true iNumber == bBoolean; // Geeft false iNumber === bBoolean; // Retourneert true iNumber = 1; bBoolean = true; iNummer == bBoolean; // Geeft false iNumber === bBoolean;
Op dit punt zou u een patroon moeten opmerken: wanneer u waarden van verschillende typen vergelijkt, kan JavaScript correct waarden afdwingen, maar het levert het meest nauwkeurige resultaat op wanneer u de operator voor strikte gelijkheid gebruikt.
Laten we tot slot een voorbeeld bekijken waarin tekenreeksen, getallen en booleans worden gecombineerd.
var sVoorbeeld, iVoorbeeld, bVoorbeeld; sExample = '1'; iExample = 1; bExample = true; // Retourneert true sExample == iExample; // Geeft false sExample === iExample; // Retourneert true iExample == bExample; // Geeft false iExample === bExample; // Geeft true sExample == bExample; // Retourneert false sExample === bExample;
Merk op dat dit basisvergelijkingen zijn; echter, wanneer gedaan in de context van een if / else
of if / else if / else
je ziet hoe het de stroom van controle door het voorwaardelijke kan verstoren.
Merk op dat bij het uitvoeren van logische bewerkingen zoals &&
en ||
evenals bitwise operatoren zoals &
en |
dat de dwangregels nog steeds van toepassing zijn. Hiertoe wilt u ervoor zorgen dat wanneer u deze bewerkingen uitvoert, waarden van exact hetzelfde type worden gebruikt om de meest nauwkeurige resultaten te krijgen.
Anders kan dwang resulteren in een vals positief of een vals negatief.
Dit completeert onze vluchtige, beginnende blik op datatypes en type dwang in een dynamisch getypeerde taal. Uiteindelijk moeten de vuistregels altijd strikte gelijkheidsoperatoren gebruiken en ervoor zorgen dat de variabelen waarmee u werkt van hetzelfde type zijn. Als je het niet zeker weet, kun je ze altijd expliciet converteren met strategieën die we eerder in de serie hebben beschreven.
In deze hele reeks hebben we bekeken hoe soorten variëren en zich gedragen van sterk getypeerde talen tot zwak getypeerde talen. We hebben gekeken hoe cast en dwang verschillen, en we hebben een aantal van de mogelijke valkuilen bekeken die kunnen leiden tot te veel vertrouwen op de tolk of de compiler bij het uitvoeren van vergelijkingen..
Ten slotte hebben we enkele strategieën bekeken voor het schrijven van meer defensieve code door ervoor te zorgen dat we het gegevenstype hebben dat we nodig hebben en hoe we strikte vergelijkingsexploitanten moeten gebruiken om ervoor te zorgen dat we de resultaten krijgen die we nodig hebben.
Zoals eerder vermeld, hebben we JavaScript gebruikt voor de doeleinden van onze voorbeelden in deze serie artikelen, maar andere zwak getypte talen zijn onderhevig aan dezelfde valkuilen. Hoe ze hun dwangvoorrang bepalen, variëren, maar de strategieën die in deze serie worden geschetst, moeten helpen bij het schrijven van meer veerkrachtige code bij het werken in zwak getypte talen.