TLDR: constrângeți-vă să utilizați triple egali.

Am găsit neintenționat acest meme JavaScript pe Reddit și este cel mai bun pe care l-am văzut vreodată.

best-js-meme-to-date-2

Puteți verifica acuratețea acestui meme executând fiecare fragment de cod în Instrumentele pentru dezvoltatori. Rezultatul nu este surprinzător, dar totuși cam dezamăgitor.

Desigur, acest mic experiment m-a determinat să mă întreb …

De ce se întâmplă acest lucru?

de ce se întâmplă asta

Cu experiență, am învățat să îmbrățișez părțile netede ale JavaScript-ului, în timp ce-mi îngrijesc pinii înțepători. Cu toate acestea, detaliile acestui caz de colț încă m-au șters.

Așa cum spune Kyle Simpson …

“Nu cred că cineva îl cunoaște vreodată pe JS, nu oricum complet.”

Când apar aceste cazuri, cel mai bine este să consultați sursa – specificație oficială ECMAScript din care este creat JavaScript.

Cu specificațiile în mână, să înțelegem profund ce se întâmplă aici.

Panoul 1 – Introducerea constrângerii

panou-1-1

Dacă alergi 0 == "0" în consola pentru dezvoltatori, de ce se întoarce true?

0 este un număr și "0" este un șir, nu ar trebui să fie niciodată la fel! Majoritatea limbajelor de programare respectă acest lucru. 0 == "0" în Java, de exemplu, returnează acest lucru:

error: incomparable types: int and String

Acest lucru are un sens perfect. Dacă doriți să comparați un int și un șir în Java, trebuie mai întâi să le convertiți în același tip.

Dar acesta este JavaScript, toți!
acesta-este-javascript

Când comparați două valori prin ==, una dintre valori poate suferi constrângere.

Constrângere-Automat schimbarea unei valori de la un tip la altul.

Automat este cuvântul cheie aici. In locul tau explicit convertindu-vă tipurile, JavaScript o face pentru dvs. în culise.

scumbag-javascript

Acest lucru este convenabil dacă îl exploatezi în mod intenționat, dar potențial dăunător dacă nu știi implicațiile acestuia.

Iată oficialul Specificația limbii ECMAScript pe asta. Parafrazez partea relevantă:

Dacă x este Număr și y este Șir, returnează x == ToNumber (y)

Deci pentru cazul nostru de 0 == "0":

Deoarece 0 este Număr și „0” este Șir, returnează 0 == ToNumber („0”)

Șirul nostru "0" a fost convertit în secret în 0, și acum avem un meci!

0 == "0" // true
// The second 0 became a number!
// so 0 equals 0 is true....

acel șir-a devenit-secret-un-număr

Ciudat nu? Ei bine, obișnuiește-te, nici măcar nu am terminat.

Panoul 2 – Tablourile devin prea constrânse

panoul-2

Această prostie nu se limitează la primitive cum ar fi șiruri, numere sau booleeni. Iată următoarea noastră comparație:

0 == [] // true
// What happened...?

Din nou constrângere! Parafrazez partea relevantă a specificației:

Dacă x este Șir sau Număr și y este Obiect, returnează x == ToPrimitive (y)

Trei lucruri aici:

1. Da, matricile sunt obiecte

matrici-sunt-obiecte

Îmi pare rău să-l rupe tu.

2. Matricea goală devine șir gol

Din nou conform spec, JS caută mai întâi un obiect toString metodă de constrângere.

În cazul matricilor, toString se alătură tuturor elementelor sale și le returnează ca un șir.

[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"

Deoarece matricea noastră este goală, nu mai avem nimic de alăturat! Prin urmare…

[].toString() // ""

goal-array-coerces-to-goal-string-1

Specificațiile ToPrimitive transformă această matrice goală într-un șir gol. Referințele sunt Aici și Aici pentru comoditate (sau confuzie).

3. Șirul gol devine apoi 0

șiruri-goale-devin-0

Nu poți să inventezi aceste lucruri. Acum că am forțat matricea la "", ne-am întors la primul algoritm …

Dacă x este Number și y este String, returnează x == ToNumber (y)

Prin urmare 0 == ""

Deoarece 0 este Număr și “” este Șir, returnează 0 == ToNumber (“”)

ToNumber("") returnează 0.

Prin urmare, 0 == 0 încă o dată…

constrângere-de-fiecare-dată-2

Panoul 3 – Recapitulare rapidă

panou-3-1

Asta este adevărat

0 == "0" // true

Pentru că constrângerea transformă acest lucru în 0 == ToNumber("0").

Asta este adevărat

0 == [] // true

Deoarece constrângerea se execută de două ori:

  1. ToPrimitive([]) dă șir gol
  2. Apoi ToNumber("") dă 0.

Atunci spune-mi … conform regulilor de mai sus, ce ar trebui să revină?

"0" == []

Panoul 4 – FALS!

panoul-4-1

FALS! Corect.

Această parte are sens dacă ați înțeles regulile.

Iată comparația noastră:

"0" == [] // false

Referindu-vă din nou la specificații:

Dacă x este Șir sau Număr și y este Obiect, returnează x == ToPrimitive (y)

Asta inseamna…

Deoarece “0” este String și [] este obiect, returnează x == ToPrimitive ([])

ToPrimitive([]) returnează șirul gol. Comparația a devenit acum

"0" == ""

"0" și "" sunt ambele șiruri, așa că JavaScript spune nu mai este nevoie de constrângere. Acesta este motivul pentru care obținem false.

Concluzie

doar-folosește-triplu-egal

Folosiți triple egal și dormiți bine noaptea.

0 === "0" // false
0 === [] // false
"0" === [] // false

Evită forțarea în totalitate, așa că cred că este și mai eficientă!

Dar creșterea performanței este aproape lipsită de sens. Câștigul real este încrederea sporită pe care o veți avea în codul dvs., ceea ce face ca acea tastare suplimentară să merite în totalitate.

Vrei antrenament gratuit?

Dacă doriți să programați un liber Apel de 15-30 minute pentru a discuta întrebări de dezvoltare Front-End cu privire la cod, interviuri, carieră sau orice altceva urmărește-mă pe Twitter și DM.

După aceea, dacă vă bucurați de prima noastră întâlnire, putem discuta despre o relație de coaching continuă care vă va ajuta să vă atingeți obiectivele de dezvoltare Front-End!

Mulțumesc pentru lectură

Pentru mai mult conținut de genul acesta, verificați https://yazeedb.com!

Pana data viitoare!