Den bedste JavaScript-meme, jeg nogensinde har set, forklaret i detaljer
TLDR: Tving dig selv til at bruge tredobbelt lig.
Jeg har utilsigtet fundet dette JavaScript-meme på Reddit, og det er det bedste, jeg nogensinde har set.
Du kan kontrollere dette memmes nøjagtighed ved at køre hvert kodestykke i Developer Tools. Resultatet er ikke overraskende, men stadig lidt skuffende.
Selvfølgelig får dette lille eksperiment mig til at undre mig ...
Hvorfor sker dette?
Med erfaring har jeg lært at omfavne JavaScript's glatte sider, mens jeg bevæger sine stikkende fyrretræer. Ikke desto mindre kaldte detaljerne i dette hjørnesag mig stadig.
Det er ligesom Kyle Simpson siger ...
"Jeg tror ikke, nogen nogensinde virkelig kender JS, ikke alligevel."
Når disse sager dukker op, er det bedst at konsultere kilden - den officielle ECMAScript-specifikation, som JavaScript er bygget fra.
Med spec i hånden, lad os dybt forstå, hvad der foregår her.
Panel 1 - Introduktion af tvang
Hvis du kører 0 == "0"
i din udviklerkonsol, hvorfor vender den tilbage true
?
0
er et tal og "0"
er en streng, de skal aldrig være det samme! De fleste programmeringssprog respekterer det. 0 == "0"
i Java returnerer for eksempel dette:
error: incomparable types: int and String
Dette giver perfekt mening. Hvis du vil sammenligne en int og streng i Java, skal du først konvertere dem til samme type.
Men dette er JavaScript, I'all!
Når du sammenligner to værdier via ==
, kan en af værdierne underkastes tvang .
Tvang - Ændring af en værdi automatisk fra en type til en anden.
Automatisk er nøgleordet her. I stedet for at du eksplicit konverterer dine typer, gør JavaScript det for dig bag kulisserne.
Dette er praktisk, hvis du bevidst udnytter det, men potentielt skadeligt, hvis du ikke er opmærksom på dets implikationer.
Her er den officielle ECMAScript Language Specification om det. Jeg omskriver den relevante del:
Hvis x er tal og y er streng, returneres x == til nummer (y)
Så for vores sag om 0 == "0"
:
Da 0 er nummer og "0" er streng, returneres 0 == til nummer ("0")
Vores streng "0"
er hemmeligt konverteret til 0
, og nu har vi en kamp!
0 == "0" // true // The second 0 became a number! // so 0 equals 0 is true....
Underligt, ikke? Nå vænne sig til det, vi er ikke engang halvvejs færdige.
Panel 2 - Arrays bliver også tvunget
Denne vrøvl er ikke begrænset til primitive som strenge, tal eller booleanske. Her er vores næste sammenligning:
0 == [] // true // What happened...?
Tvang igen! Jeg omskriver specs relevante del:
Hvis x er streng eller tal, og y er objekt, skal du returnere x == ToPrimitive (y)
Tre ting her:
1. Ja, arrays er objekter
Undskyld at bryde det dig.
2. Tom matrix bliver tom streng
Igen ifølge specifikationen leder JS først efter et objekts toString
metode til at tvinge det.
I tilfælde af arrays toString
slutter det sig til alle dets elementer og returnerer dem som en streng.
[1, 2, 3].toString() // "1,2,3" ['hello', 'world'].toString() // "hello,world"
Da vores array er tomt, har vi intet at deltage i! Derfor...
[].toString() // ""
Specifikationerne ToPrimitive
forvandler dette tomme array til en tom streng. Referencer er her og her for din bekvemmelighed (eller forvirring).
3. Tom streng bliver derefter 0
Du kan ikke finde på disse ting. Nu hvor vi har tvunget arrayet til ""
, er vi tilbage til den første algoritme ...
Hvis x er tal og y er streng, returneres x == til nummer (y)
Så for 0 == ""
Da 0 er nummer og "" er streng, returneres 0 == til nummer ("")
ToNumber("")
returnerer 0.
Derfor 0 == 0
endnu en gang ...
Panel 3 - Hurtig opsummering
Det er rigtigt
0 == "0" // true
Fordi tvang gør dette til 0 == ToNumber("0")
.
Det er rigtigt
0 == [] // true
Fordi tvang løber to gange:
ToPrimitive([])
giver tom strengToNumber("")
Giver derefter 0.
Så fortæl mig ... i henhold til ovenstående regler, hvad skal dette returnere?
"0" == []
Panel 4 - FALSK!
FALSK! Korrekt.
Denne del giver mening, hvis du har forstået reglerne.
Her er vores sammenligning:
"0" == [] // false
Henviser til specifikationen igen:
Hvis x er streng eller tal, og y er objekt, skal du returnere x == ToPrimitive (y)
Det betyder...
Da "0" er streng og [] er objekt, returneres x == ToPrimitive ([])
ToPrimitive([])
returnerer tom streng. Sammenligningen er nu blevet
"0" == ""
"0"
og ""
er begge strenge, så JavaScript siger, at der ikke er behov for mere tvang . Det er derfor, vi får false
.
Konklusion
Brug tredobbelt lig og sov godt om natten.
0 === "0" // false 0 === [] // false "0" === [] // false
Det undgår tvang fuldstændigt, så jeg antager, at det også er mere effektivt!
Men præstationsforøgelsen er næsten meningsløs. Den virkelige gevinst er den øgede tillid, du har til din kode, hvilket gør det ekstra tastetryk helt umagen værd.
Vil du have gratis coaching?
Hvis du vil planlægge et gratis opkald på 15-30 minutter for at diskutere Front-End-udviklingsspørgsmål vedrørende kode, interviews, karriere eller andet, følg mig på Twitter og DM mig.
Derefter, hvis du nyder vores første møde, kan vi diskutere et løbende coachingforhold, der hjælper dig med at nå dine Front-End-udviklingsmål!
Tak for læsningen
For mere indhold som dette, se //yazeedb.com!
Indtil næste gang!