Hackai, skirti kurti „JavaScript“ masyvus

Įžvalgūs masyvų kūrimo ir klonavimo „JavaScript“ patarimai.

Labai svarbus kiekvienos programavimo kalbos aspektas yra kalboje galimi duomenų tipai ir struktūros. Daugelyje programavimo kalbų pateikiami duomenų tipai, skirti atvaizduoti ir dirbti su sudėtingais duomenimis. Jei dirbote su tokiomis kalbomis kaip „Python“ arba „Ruby“, turėtumėte matyti tokių duomenų tipus kaip sąrašai , rinkiniai , rinkiniai , maišos , diktantai ir pan.

„JavaScript“ nėra tiek daug sudėtingų duomenų tipų - jūs tiesiog turite masyvus ir objektus . Tačiau ES6 kalboje buvo pridėti keli duomenų tipai ir struktūros, pvz., Simboliai , rinkiniai ir žemėlapiai .

Masyvai „JavaScript“ yra aukšto lygio objektai, panašūs į sąrašą, turintys ilgio ypatybę ir sveiko skaičiaus ypatybes kaip indeksus.

Šiame straipsnyje dalinuosi keliais įsilaužimais kuriant naujus „JavaScript“ masyvus arba klonuojant jau esamus.

Masyvų kūrimas: masyvų konstruktorius

Populiariausias masyvų kūrimo būdas yra masyvo pažodinės sintaksės naudojimas, kuris yra labai paprastas. Tačiau kai norite dinamiškai kurti masyvus, masyvo pažodinė sintaksė ne visada gali būti geriausias būdas. Alternatyvus metodas yra Arraykonstruktoriaus naudojimas.

Čia yra paprastas kodo fragmentas, parodantis Arraykonstruktoriaus naudojimą.

Iš ankstesnio fragmento galime pamatyti, kad Arraykonstruktorius masyvus kuria skirtingai, priklausomai nuo gautų argumentų.

Naujos masyvai: su apibrėžtu ilgiu

Pažvelkime atidžiau, kas nutinka kuriant Arraytam tikro ilgio naujieną. Konstruktorius tiesiog nustato lengthmasyvo ypatybę iki nurodyto ilgio, nenustatydamas raktų.

Iš pirmiau pateikto fragmento galite susigundyti manydami, kad kiekvienam masyvo raktui buvo nustatyta reikšmė undefined. Tačiau realybė yra ta, kad tie raktai niekada nebuvo nustatyti (jų nėra).

Ši iliustracija daro ją aiškesnę:

Todėl nenaudinga bandyti naudoti bet kurį masyvo kartojimo metodą, pvz. map(), filter()Arba reduce()manipuliuoti masyvu. Tarkime, kad kiekvieną masyvo indeksą norime užpildyti skaičiumi 5kaip verte. Bandysime taip:

Matome, kad map()čia neveikė, nes masyvo indekso ypatybių nėra - egzistuoja tik lengthypatybė.

Pažiūrėkime, kaip galime išspręsti šią problemą įvairiais būdais.

1. Naudojant Array.prototype.fill ()

fill()Metodas užpildo visus masyvo iš pradžios indeksas galutiniam indeksą su statinio vertės elementus. Pabaigos indeksas neįtrauktas. Daugiau apie tai galite sužinoti fill()čia.

Atminkite, kad tai fill()veiks tik naršyklėse su ES6 palaikymu.

Štai paprasta iliustracija:

Čia mes sugebėjome užpildyti visus mūsų sukurto masyvo elementus 5. Naudodami fill()metodą, galite nustatyti bet kokią statinę vertę skirtingiems masyvo indeksams .

2. Naudojant Array.from ()

Array.from()Metodas sukuria naują, seklių-nukopijuotas Arrayinstancija iš masyvo pavidalo ar iterable objektą. Daugiau apie tai galite sužinoti Array.from()čia.

Atminkite, kad tai Array.from()veiks tik naršyklėse su ES6 palaikymu.

Štai paprasta iliustracija:

Dabar mes turime tikrąsias undefinedkiekvieno masyvo elemento reikšmes Array.from(). Tai reiškia, kad dabar mes galime eiti į priekį ir naudoti tokius metodus kaip .map()ir .filter()masyvas, nes dabar egzistuoja indekso ypatybės.

Dar verta atkreipti dėmesį į Array.from()tai, kad tam gali prireikti antro argumento, kuris yra žemėlapio funkcija. Jis bus iškviestas ant kiekvieno masyvo elemento. Dėl to nebereikia skambinti .map()paskui Array.from().

Štai paprastas pavyzdys:

3. Naudodamiesi „Spread Operator“

Plitimas operatorius( ...), pridėta ES6, galima naudoti masyvo elementams paskleisti, nustatant trūkstamų elementų vertę undefined. Tai duos tą patį rezultatą kaip paprasčiausias skambinimas Array.from()naudojant tik masyvą kaip vienintelis argumentas.

Čia yra paprasta sklaidos operatoriaus naudojimo iliustracija:

Galite tęsti ir naudoti tokius metodus kaip .map()ir .filter()masyve, nes dabar egzistuoja indekso ypatybės.

Naudojant Array.of ()

Elgiasi labai panašiai, kaip matėme kuriant naujus masyvus naudojant Arraykonstruktorių ar funkciją Array.of(). Tiesą sakant, vienintelis skirtumas tarp Array.of()ir Arrayyra tai, kaip jie tvarko vieną jiems perduotą sveiko skaičiaus argumentą.

Nors Array.of(5)sukuria naują masyvą su vienu elementu 5ir ilgio savybę 1, Array(5)sukuria naują tuščią masyvą su 5 tuščiomis sritimis ir ilgio ypatybę 5.

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

Be šio esminio skirtumo, Array.of()elgiasi taip pat, kaip ir Arraykonstruktorius. Daugiau apie tai galite sužinoti Array.of()čia.

Atminkite, kad tai Array.of()veiks tik naršyklėse su ES6 palaikymu.

Konvertuoti į masyvus: masyvo patinkantys ir kartojami

Jei rašote „JavaScript“ funkcijas pakankamai ilgai, jau turėtumėte žinoti apie argumentsobjektą - tai yra į masyvą panašus objektas, prieinamas kiekvienoje funkcijoje, kad būtų galima laikyti argumentų, kuriuos gavo funkcija, sąrašą. Nors argumentsobjektas panašus į masyvą, jis neturi prieigos prie Array.prototypemetodų.

Iki ES6 bandydami konvertuoti argumentsobjektą į masyvą, paprastai pamatėte tokį kodo fragmentą :

Naudodami Array.from()operatorių arba išplitimo operaciją, bet kurį į masyvą panašų objektą galite patogiai konvertuoti į masyvą. Taigi, užuot tai padarę:

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

galite atlikti bet kurį iš šių būdų:

// Using Array.from() var args = Array.from(arguments); // Using the Spread operator var args = [...arguments];

Tai taip pat taikoma kartotiniams, kaip parodyta šioje iliustracijoje:

Atvejo analizė: diapazono funkcija

Prieš tęsdami atvejo tyrimą, sukursime paprastą range()funkciją, kad įdiegtume naują masyvo nulaužimą, kurį ką tik išmokome. Funkcija turi tokį parašą:

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

Štai kodo fragmentas:

Šiame kodo fragmente mes Array.from()sukūrėme naują dinaminio ilgio diapazono masyvą ir tada užpildėme jį nuosekliai didinamais skaičiais, pateikdami susiejimo funkciją.

Atminkite, kad aukščiau pateiktas kodo fragmentas neveiks naršyklėse be ES6 palaikymo, išskyrus atvejus, kai naudojate polifildus.

Štai keletas rezultatų, iškviečiant range()funkciją, apibrėžtą aukščiau esančiame kodo fragmente:

Tiesioginę kodo demonstracinę versiją galite gauti paleidę šį rašiklį „ Codepen“ :

Klonavimo masyvai: iššūkis

„JavaScript“ masyvai ir objektai yra nuorodų tipai. Tai reiškia, kad kai kintamajam priskiriamas masyvas ar objektas, tai, kas priskiriama kintamajam, yra nuoroda į vietą atmintyje, kurioje buvo saugomas masyvas ar objektas.

Masyvai, kaip ir visi kiti „JavaScript“ objektai, yra nuorodų tipai. Tai reiškia, kad masyvai kopijuojami pagal nuorodą, o ne pagal vertę.

Tokiu būdu saugant nuorodų tipus, kyla šios pasekmės:

1. Panašūs masyvai nėra lygūs.

Čia matome, kad nors juose array1ir array2yra tos pačios masyvo specifikacijos, jie nėra lygūs. Taip yra todėl, kad nuoroda į kiekvieną masyvą nurodo skirtingą atminties vietą.

2. Masyvai kopijuojami pagal nuorodą, o ne pagal vertę.

Čia mes bandome nukopijuoti array1į array2, bet tai, ką mes iš esmės darome, yra nukreipimas array2į tą pačią atminties vietą, kuri array1rodo. Taigi, abu array1ir array2nurodo tą pačią vietą atmintyje ir yra lygūs.

Tai reiškia, kad kai mes pakeičiame array2, pašalindami paskutinį elementą, paskutinis elementas array1taip pat pašalinamas. Tai yra todėl, kad pokyčiai iš tikrųjų buvo padaryta masyvo saugomi atmintyje, o array1ir array2yra tik rodyklės į tą pačią vietą atmintyje, kai masyvas yra saugomas.

Klonavimo matricos: „Hacks“

1. Naudojant Array.prototype.slice ()

slice()Metodas sukuria seklių kopiją masyvo dalis, nekeičiant masyvo. Daugiau apie tai galite sužinoti slice()čia.

Apgaulė yra skambinti slice()arba 0kaip vienintelį argumentą, arba be jokių argumentų:

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

Čia yra paprasta masyvo klonavimo iliustracija slice():

Čia galite pamatyti, kad array2yra klonas, array1turintis tuos pačius daiktus ir ilgį. Tačiau jie nurodo skirtingas atminties vietas ir dėl to nėra lygūs. Taip pat pastebite, kad kai mes pakeisime array2, pašalindami paskutinį elementą, tai array1nepasikeis.

2. Naudojant Array.prototype.concat ()

Šis concat()metodas naudojamas sujungti dvi ar daugiau masyvų, todėl gaunamas naujas masyvas, o pradiniai masyvai paliekami nepakitę. Daugiau apie tai galite sužinoti concat()čia.

Apgaulė yra iškviesti concat()tuščią masyvą ( []) kaip argumentą arba be jokių argumentų:

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

Masyvo klonavimas naudojant concat()yra gana panašus į slice(). Čia yra paprasta masyvo klonavimo iliustracija concat():

3. Naudojant „Array.from“ ()

Kaip matėme anksčiau, Array.from()gali būti naudojamas kuriant naują masyvą, kuris yra negili originalaus masyvo kopija. Štai paprasta iliustracija:

4. Masyvo pertvarkymo naudojimas

Naudodami ES6, įrankių rinkinyje turime keletą galingesnių įrankių, tokių kaip pertvarkymas , išplitimasoperatorius , rodyklių funkcijos ir pan. Pertvarkymas yra labai galingas įrankis duomenims iš sudėtingų tipų, tokių kaip masyvai ir objektai, išgauti.

Apgaulė yra naudoti metodą, vadinamą poilsio parametrais, kuris apima masyvo destrukcijos ir sklaidos operatoriaus derinį, kaip parodyta šiame fragmente:

let [...arrayClone] = originalArray;

Pirmiau pateiktas fragmentas sukuria kintamąjį, pavadintą, arrayClonekuris yra originalArray. Čia yra paprasta masyvo klonavimo iliustracija naudojant masyvo pertvarkymą iliustracija:

Klonavimas: negilus prieš gilų

Visi iki šiol ištirti masyvo klonavimo būdai sukuria seklią masyvo kopiją . Tai nebus problema, jei masyve yra tik primityvios reikšmės. Tačiau jei masyve yra įdėtų objektų nuorodų, šios nuorodos išliks nepažeistos net tada, kai masyvas bus klonuotas.

Štai labai paprastas to demonstravimas:

Atkreipkite dėmesį, kad modifikavus įdėtą masyvą array1modifikuotas įdėtas masyvas array2ir atvirkščiai.

Šios problemos sprendimas yra sukurti gilią masyvo kopiją ir tai padaryti galima keliais būdais.

1. JSON technika

Lengviausias būdas sukurti gilią masyvo kopiją yra naudojant JSON.stringify()ir JSON.parse().

JSON.stringify()konvertuoja „JavaScript“ vertę į galiojančią JSON eilutę, o JSON.parse()JSON eilutę - į atitinkamą „JavaScript“ vertę ar objektą.

Štai paprastas pavyzdys:

JSON technika turi tam tikrų trūkumų, ypač kai yra susijusios ne styginių, skaičių ir loginių reikšmių vertės.

Šiuos JSON technikos trūkumus daugiausia galima sieti su būdu, kuriuo JSON.stringify()metodas konvertuoja reikšmes į JSON eilutę.

Čia yra paprastas šio trūkumo bandymas parodyti JSON.stringify()vertę, kurioje yra įdėta funkcija.

2. Gilios kopijos pagalbininkas

Veiksminga JSON technikos alternatyva bus įdiegti savo giliosios kopijos pagalbinės funkcijos funkciją klonuojant nuorodų tipus, nesvarbu, ar jie būtų masyvai, ar objektai.

Čia yra labai paprasta ir minimalistinė giliosios kopijos funkcija, vadinama deepClone:

Dabar tai nėra geriausios giliųjų kopijų funkcijos, kaip netrukus pamatysite su kai kuriomis „JavaScript“ bibliotekomis, tačiau tai gana giliai atlieka gilųjį kopijavimą.

3. „JavaScript“ bibliotekų naudojimas

Ką tik apibrėžta giliosios kopijos pagalbininko funkcija nėra pakankamai tvirta klonuojant visų rūšių „JavaScript“ duomenis, kurie gali būti įterpti į sudėtingus objektus ar masyvus.

„JavaScript“ bibliotekos, pvz., „ Lodash“ ir „ jQuery“, teikia patikimesnes giliųjų kopijavimo įrankių funkcijas ir palaiko įvairius „JavaScript“ duomenis.

Štai pavyzdys, kuris naudojamas _.cloneDeep()iš Lodash bibliotekos:

Čia yra tas pats pavyzdys, bet naudojant $.extend()„jQuery“ biblioteką:

Išvada

Šiame straipsnyje mums pavyko išnagrinėti keletą būdų, kaip dinamiškai kurti naujus masyvus ir klonuoti jau esamus, įskaitant į masyvą panašių objektų ir iteratyvų pavertimą masyvais.

Mes taip pat matėme, kaip kai kurios naujos ES6 funkcijos ir patobulinimai gali padėti mums efektyviai atlikti tam tikras manipuliacijas masyvais.

Masyvams klonuoti ir paskleisti naudojome tokias funkcijas kaip destrukcija ir išplitimo operatorius. Iš šio straipsnio galite sužinoti daugiau apie pertvarkymą.

Ploti ir sekti

Jei jums pasirodė, kad šis straipsnis yra įžvalgus, galite laisvai pateikti keletą plojimų, jei to neprieštaraujate.

Taip pat galite sekti mane „Medium“ (Glad Chinda), jei norite įžvalgesnių straipsnių, kurie jums gali būti naudingi. Taip pat galite sekti mane „Twitter“ (@gladchinda).

Laimingo įsilaužimo ...