de Glad Chinda

Hacks pentru crearea matricelor JavaScript

Sfaturi utile pentru crearea și clonarea matricilor în JavaScript.

Hacks pentru crearea matricelor JavaScript
Fotografie originală de Markus Spiske pe Unsplash

Un aspect foarte important al fiecărui limbaj de programare îl reprezintă tipurile de date și structurile disponibile în limbă. Majoritatea limbajelor de programare oferă tipuri de date pentru reprezentarea și lucrul cu date complexe. Dacă ați lucrat cu limbi precum Python sau Ruby, ar fi trebuit să vedeți tipuri de date precum liste, seturi, tupluri, hashuri, scobituri, si asa mai departe.

În JavaScript, nu există atât de multe tipuri de date complexe – pur și simplu le aveți matrici și obiecte. Cu toate acestea, în ES6, au fost adăugate la limbă câteva tipuri de date și structuri, cum ar fi simboluri, seturi, și hărți.

Tablourile din JavaScript sunt obiecte de nivel înalt, asemănătoare listelor o proprietate de lungime și proprietăți întregi ca indici.

În acest articol, împărtășesc câteva hacks pentru crearea de noi matrici JavaScript sau pentru clonarea celor deja existente.

Crearea matricelor: constructorul matricii

Cea mai populară metodă de creare a matricelor este utilizarea matrice literal sintaxă, care este foarte simplă. Cu toate acestea, atunci când doriți să creați dinamic tablouri, este posibil ca sintaxa literală a matricei să nu fie întotdeauna cea mai bună metodă. O metodă alternativă este utilizarea Array constructor.

Iată un fragment de cod simplu care arată utilizarea fișierului Array constructor.

Din fragmentul anterior, putem vedea că Array constructorul creează matrici diferit în funcție de argumentele pe care le primește.

Matrice noi: cu lungime definită

Să analizăm mai atent ce se întâmplă atunci când creăm un nou Array de o lungime dată. Constructorul stabilește doar length proprietatea matricei la lungimea dată, fără a seta tastele.

1611718511 885 Hacks pentru crearea matricelor JavaScript

Din fragmentul de mai sus, ați putea fi tentat să credeți că fiecare cheie din matrice a fost setată la o valoare de undefined. Dar realitatea este că acele chei nu au fost niciodată stabilite (nu există).

Următoarea ilustrație o face mai clară:

1611718511 52 Hacks pentru crearea matricelor JavaScript

Acest lucru face inutilă încercarea de a utiliza oricare dintre metodele de iterație a matricei, cum ar fi map(), filter() sau reduce() pentru a manipula matricea. Să presupunem că vrem să completăm fiecare index din matrice cu numărul 5 ca valoare. Vom încerca următoarele:

1611718511 941 Hacks pentru crearea matricelor JavaScript

Putem vedea asta map() nu a funcționat aici, deoarece proprietățile indexului nu există în matrice – doar length proprietatea există.

Să vedem diferite moduri în care putem rezolva această problemă.

1. Utilizarea Array.prototype.fill ()

fill() metoda umple toate elementele unui tablou de la un index de start la un index de final cu o valoare statică. Indicele final nu este inclus. Puteți afla mai multe despre fill() aici.

Rețineți că fill() va funcționa numai în browsere cu suport ES6.

Iată o ilustrare simplă:

1611718511 652 Hacks pentru crearea matricelor JavaScript

Aici, am reușit să completăm toate elementele din matricea noastră creată 5. Puteți seta orice valoare statică pentru diferiți indici ai tabloului folosind fill() metodă.

2. Utilizarea Array.from ()

Array.from() metoda creează o nouă copiere superficială Array instanță dintr-un obiect asemănător matricei sau iterabil. Puteți afla mai multe despre Array.from() aici.

Rețineți că Array.from() va funcționa numai în browsere cu suport ES6.

Iată o ilustrare simplă:

1611718512 420 Hacks pentru crearea matricelor JavaScript

Aici, acum avem adevărat undefined valori setate pentru fiecare element al matricei folosind Array.from(). Aceasta înseamnă că acum putem merge mai departe și să folosim metode precum .map() și .filter() pe matrice, deoarece proprietățile indexului există acum.

Încă un lucru demn de remarcat Array.from() este că poate lua un al doilea argument, care este un funcția de hartă. Va fi apelat pe fiecare element al matricei. Acest lucru îl face apel redundant .map() după Array.from().

Iată un exemplu simplu:

1611718512 407 Hacks pentru crearea matricelor JavaScript

3. Utilizarea Spread Operator

operator de răspândire (...), adăugat în ES6, poate fi utilizat pentru a răspândi elementele matricei, setând elementele lipsă la o valoare de undefined. Acest lucru va produce același rezultat ca și simpla apelare Array.from() doar cu matricea ca singur argument.

Iată o ilustrare simplă a utilizării operatorului spread:

1611718512 271 Hacks pentru crearea matricelor JavaScript

Puteți continua și utiliza metode precum .map() și .filter() pe matrice, deoarece proprietățile indexului există acum.

Utilizarea Array.of ()

La fel cum am văzut cu crearea de noi matrici folosind Array constructor sau funcție, Array.of() se comportă într-un mod foarte asemănător. De fapt, singura diferență dintre Array.of() și Array este în modul în care gestionează un singur argument întreg transmis lor.

In timp ce Array.of(5) creează o nouă matrice cu un singur element, 5, și o proprietate de lungime de 1, Array(5) creează o nouă matrice goală cu 5 sloturi goale și o proprietate de lungime de 5.

var array1 = Array.of(5); // [5]
var array2 = Array(5); // Array(5) {length: 5}

Pe lângă această diferență majoră, Array.of() se comportă la fel ca Array constructor. Puteți afla mai multe despre Array.of() aici.

Rețineți că Array.of() va funcționa numai în browsere cu suport ES6.

Conversia la matrice: Array-like și Iterables

Dacă ați scris funcții JavaScript suficient de mult, ar trebui să știți deja despre arguments obiect – care este un asemănător matricei obiect disponibil în fiecare funcție pentru a deține lista argumentelor primite de funcție. desi arguments obiectul seamănă mult cu un tablou, nu are acces la Array.prototype metode.

Înainte de ES6, de obicei, veți vedea un fragment de cod, cum ar fi următorul, atunci când încercați să convertiți fișierul arguments obiectează la o matrice:

1611718512 480 Hacks pentru crearea matricelor JavaScript

Cu Array.from() sau operatorul spread, puteți converti în mod convenabil orice obiect de tip matrice într-un tablou. Prin urmare, în loc să faceți acest lucru:

var args = Array.prototype.slice.call(arguments);

puteți face oricare dintre următoarele:

// Using Array.from()
var args = Array.from(arguments);

// Using the Spread operator
var args = [...arguments];

Acestea se aplică și pentru iterabile așa cum se arată în următoarea ilustrație:

1611718513 620 Hacks pentru crearea matricelor JavaScript

Studiu de caz: Funcția Range

Ca studiu de caz înainte de a continua, vom crea un simplu range() funcția de implementare a noului hack de matrice tocmai am învățat. Funcția are următoarea semnătură:

range(start: number, end: number, step: number) => Array<number>

Iată fragmentul de cod:

În acest fragment de cod, am folosit Array.from() pentru a crea noua gamă de game de lungime dinamică și apoi pentru a-l completa numere incrementate secvențial, oferind o funcție de mapare.

Rețineți că fragmentul de cod de mai sus nu va funcționa pentru browserele fără suport ES6, cu excepția cazului în care utilizați polifilări.

Iată câteva rezultate din apelarea la range() funcție definită în fragmentul de cod de mai sus:

1611718513 818 Hacks pentru crearea matricelor JavaScript

Puteți obține o demonstrație de cod live executând următorul stilou pe Codepen:

Clonarea matricilor: provocarea

În JavaScript, tablourile și obiectele sunt tipuri de referință. Aceasta înseamnă că atunci când unei variabile i se atribuie un tablou sau un obiect, ceea ce este atribuit variabilei este o referință la locația din memorie în care a fost stocat tabloul sau obiectul.

Tablourile, la fel ca orice alt obiect din JavaScript, sunt tipuri de referință. Aceasta înseamnă că tablourile sunt copiate prin referință și nu prin valoare.

Stocarea tipurilor de referință în acest mod are următoarele consecințe:

1. Matrice similare nu sunt egale.

1611718513 439 Hacks pentru crearea matricelor JavaScript

Aici, vedem asta deși array1 și array2 conțin aparent aceleași specificații matrice, nu sunt egale. Acest lucru se datorează faptului că referința la fiecare dintre matrice indică o locație diferită în memorie.

2. Tablourile sunt copiate prin referință și nu după valoare.

1611718513 273 Hacks pentru crearea matricelor JavaScript

Aici, încercăm să copiem array1 la array2, dar ceea ce facem practic este indicarea array2 în aceeași locație din memorie pe care array1 arata spre. Prin urmare, ambele array1 și array2 indică aceeași locație din memorie și sunt egale.

Implicația este că atunci când facem o schimbare la array2 prin eliminarea ultimului element, ultimul element din array1 de asemenea, este eliminat. Acest lucru se datorează faptului că modificarea a fost efectiv făcută matricei stocate în memorie, întrucât array1 și array2 sunt doar indicii către aceeași locație din memorie în care este stocată matricea.

Clonarea matricilor: Hacks-urile

1. Utilizarea Array.prototype.slice ()

slice() metoda creează o copie superficială a unei porțiuni dintr-o matrice fără a modifica matricea. Puteți afla mai multe despre slice() aici.

Trucul este să suni slice() fie cu0 ca singur argument sau fără niciun argument:

// with O as only argument
array.slice(0);

// without argument
array.slice();

Iată o ilustrare simplă a clonării unui tablou cu slice():

1611718514 350 Hacks pentru crearea matricelor JavaScript

Aici, puteți vedea asta array2 este o clonă a array1 cu aceleași articole și lungime. Cu toate acestea, ele indică diferite locații din memorie și, ca urmare, nu sunt egale. De asemenea, observați că atunci când modificăm array2 prin eliminarea ultimului element, array1 ramane neschimbat.

2. Utilizarea Array.prototype.concat ()

concat() metoda este utilizată pentru a îmbina două sau mai multe tablouri, rezultând o nouă matrice, în timp ce matricile originale sunt lăsate neschimbate. Puteți afla mai multe despre concat() aici.

Trucul este să suni concat() fie cu o matrice goală ([]) ca argument sau fără niciun argument:

// with an empty array
array.concat([]);

// without argument
array.concat();

Clonarea unui tablou cu concat() este destul de similar cu utilizarea slice(). Iată o ilustrare simplă a clonării unui tablou cu concat():

1611718514 300 Hacks pentru crearea matricelor JavaScript

3. Utilizarea Array.from ()

Așa cum am văzut mai devreme, Array.from() poate fi folosit pentru a crea o nouă matrice care este o copie superficială a matricei originale. Iată o ilustrare simplă:

1611718514 850 Hacks pentru crearea matricelor JavaScript

4. Utilizarea Array Destructuring

Cu ES6, avem câteva instrumente mai puternice în cutia noastră de instrumente, cum ar fi destructurare, răspândire operator, funcții săgeată, si asa mai departe. Destructurarea este un instrument foarte puternic pentru extragerea datelor din tipuri complexe precum matrici și obiecte.

Trucul este să folosești o tehnică numită parametrii de odihnă, care implică o combinație de destructurare a matricei și operatorul de răspândire așa cum se arată în următorul fragment:

let [...arrayClone] = originalArray;

Fragmentul de mai sus creează o variabilă numită arrayClone care este o clonă a originalArray. Iată o ilustrare simplă a clonării unui tablou folosind destructurarea matricii:

1611718514 32 Hacks pentru crearea matricelor JavaScript

Clonarea: Shallowow versus Deep

Toate tehnicile de clonare matrice pe care le-am explorat până acum produc un copie superficială a matricei. Aceasta nu va fi o problemă dacă matricea conține doar valori primitive. Cu toate acestea, dacă matricea conține referințe de obiecte imbricate, acele referințe vor rămâne intacte chiar și atunci când matricea este clonată.

Iată o demonstrație foarte simplă a acestui lucru:

1611718514 300 Hacks pentru crearea matricelor JavaScript

Observați că modificarea matricei imbricate în array1 a modificat, de asemenea, matricea imbricată în array2 si invers.

Soluția la această problemă este crearea unui copie profundă din matrice și există câteva modalități de a face acest lucru.

1. Tehnica JSON

Cel mai simplu mod de a crea o copie profundă a unui tablou este prin utilizarea unei combinații de JSON.stringify() și JSON.parse().

JSON.stringify() convertește o valoare JavaScript într-un șir JSON valid, în timp ce JSON.parse() convertește un șir JSON într-o valoare sau obiect JavaScript corespunzător.

Iată un exemplu simplu:

1611718514 894 Hacks pentru crearea matricelor JavaScript

Tehnica JSON are unele defecte mai ales atunci când sunt implicate alte valori decât șirurile, numerele și booleenii.

Aceste defecte în tehnica JSON pot fi atribuite în mod major modului în care JSON.stringify() metoda convertește valorile în șir JSON.

Iată o demonstrație simplă a acestui defect în încercarea de a JSON.stringify() o valoare care conține funcția imbricată.

1611718514 362 Hacks pentru crearea matricelor JavaScript

2. Deep Copy Helper

O alternativă viabilă la tehnica JSON va fi să vă implementați propria funcție de ajutor copiere profundă pentru clonarea tipurilor de referință, fie că sunt matrice sau obiecte.

Iată o funcție de copiere profundă foarte simplă și minimalistă numită deepClone:

Acum, aceasta nu este cea mai bună funcție de copiere profundă, așa cum veți vedea în curând cu unele biblioteci JavaScript – cu toate acestea, realizează o copiere profundă într-o măsură destul de bună.

1611718514 81 Hacks pentru crearea matricelor JavaScript

3. Utilizarea bibliotecilor JavaScript

Funcția de asistență pentru copierea profundă pe care tocmai am definit-o nu este suficient de robustă în clonarea tuturor tipurilor de date JavaScript care pot fi cuibărite în obiecte sau matrice complexe.

Bibliotecile JavaScript cum ar fi Lodash și jQuery oferiți funcții de utilitate de copiere profundă mai robuste, cu suport pentru diferite tipuri de date JavaScript.

Iată un exemplu care folosește _.cloneDeep() din biblioteca Lodash:

1611718514 615 Hacks pentru crearea matricelor JavaScript

Iată același exemplu, dar folosind $.extend() din biblioteca jQuery:

1611718514 175 Hacks pentru crearea matricelor JavaScript

Concluzie

În acest articol, am reușit să explorăm mai multe tehnici pentru crearea dinamică de noi matrici și clonarea celor deja existente, inclusiv conversia obiectelor asemănătoare matricei și iterabile în matrici.

De asemenea, am văzut cum unele dintre noile caracteristici și îmbunătățiri introduse în ES6 ne pot permite să efectuăm în mod eficient anumite manipulări pe tablouri.

Am folosit caracteristici precum destructurarea și operatorul de răspândire pentru clonarea și împrăștierea matricelor. Puteți afla mai multe despre destructurare din Acest articol.

Clap & Follow

Dacă ați găsit acest articol perspicace, sunteți liber să dați câteva runde de aplauze dacă nu vă deranjează.

De asemenea, mă puteți urmări pe Medium (Glad Chinda) pentru articole mai perspicace pe care le-ați putea găsi de ajutor. De asemenea, mă puteți urmări pe Twitter (@gladchinda).

Hacking fericit …