Kolm JavaScripti massiivi saladust, millest te ei pruugi teada. Elementide arv ei näita massiivi tegelikku suurust. Teisendage reaalseks massiiviks

Kell JavaScripti õppimine objektid, kohtame me kõik fraase nagu " Massiivid on lihtsad objektid Javascriptis" Täna tahan seda väidet lähemalt uurida:

Vaata näidet

Kui vaatate ülaltoodud näidet, saab selgeks, et massiiv on objektitüüp. Aga mida see tähendab?

Kui te ei ole tuttav operaatori tüüp, siis saad selle kohta rohkem teada siit.

Pärand

Objektide ja massiividega töötamise JavaScripti erinevuse mõistmiseks vaatame pärimise põhimõtet.

Iga objekt sisaldab viidet oma põhiobjektile (prototüübile). Kui kutsute meetodit, otsib JavaScript seda objektist, millega töötate. Kui meetodit ei leita, alustatakse prototüübi otsimist. Otsitakse kogu prototüübiahela ulatuses, kuni leitakse meetod või jõutakse juurobjektini.

Vaata näidet

Ülaltoodud näide loob isikuobjekti oma nimeparameetriga. Kui kutsutakse meetod toString, kontrollitakse esmalt isikuobjekti, millele järgneb selle prototüübi ( Objekt.prototüüp). Kasutab prototüübi loogikat, mis tavaliselt tagastab .

Objektide ja massiivide erinevus

Massiividel on traditsioonilistest JavaScripti objektidest olulisi erinevusi. Põhjus peitub objektis Array.prototype, mis esindab kõiki massiividele omaseid meetodeid. Iga uus massiiv pärib need meetodid massiivist.prototype .

Oluline on märkida, et prototüübi atribuudi väärtus failis Array.prototype on Object.prototype . See tähendab, et massiivid on vaid objektid, kuid koos täiendavaid meetodeid. Objekt ei tee midagi, mida massiiv ei saaks teha.

Vaata näidet

Veiderused

Nagu JavaScripti objektidel, on ka massiividel oma veidrused.

Indekseerimata omadused

Kuna massiivid on lihtsalt objektid, saate neile rakendada indekseerimata omadusi. See on tavaliselt esimene asi, mis üllatab. Allolevas näites määran kaks indekseerimata atribuuti, mida nimetatakse sorteeritud ja autor toidukaupade array.

Märkus. Nagu objektide puhul, toetatakse nii punkti kui ka sulgu.

Vaata näidet

pikkus

Ka massiivi pikkusomadus tekitab sageli segadust. Seda omadust aetakse sageli segamini massiivi elementide loendamisega. Pikkus on aga arvuliselt suurem kui suurima massiivi indeks. Seetõttu ei mõjuta indekseerimata omadused massiivi pikkust, nagu on näidatud näites.

Teine olukord, kus pikkus võib olla eksitav, on see, kui proovime lisada elementi, mille indeks on suurem kui praeguse pikkuse massiivi väärtus. Pange tähele, et näites hüppas massiivi pikkus 2-lt 10-le kohe pärast kolmanda elemendi lisamist massiivi indeksi 9 juures.

Kui atribuudi pikkus väärtus muutub, eemaldatakse kõik elemendid, mille indeks on uuest pikkusest kõrgemal.

Märkus.

Õige pikkuse väärtuse saamiseks võite kasutada Object.keys(groceries).length . Pange tähele, et see hõlmab ka indekseerimata omadusi, kuni määrate need loendamatuks. See on:

Object.defineProperty(toidukaubad, "sorted", ( väärtus: false, loendatav: false, konfigureeritav: tõene, kirjutatav: tõene ));

Mida me siis tegema peaksime?

Kui teil on vaja luua atribuutide kogu erinevat tüüpi, kasutage objektide loomiseks JavaScripti. Kõigil muudel juhtudel võite kasutada massiivi.

Artikli “JavaScript: Arrays vs Objects” tõlke valmistas ette sõbralik projektimeeskond.

  • Tõlge
  • I. Reaalmassiivide itereerimine
    1. iga meetodi ja sellega seotud meetodite jaoks
    2. silmuse jaoks
    3. Õige kasutamine for...silmuses
    4. for... of loop (iteraatori kaudne kasutamine)
    5. Iteraatori selgesõnaline kasutamine
    1. Meetodite kasutamine reaalsete massiivide itereerimiseks
    2. Teisendage reaalseks massiiviks
    3. Märkus käitusaegsete objektide kohta

I. Reaalmassiivide itereerimine

Sees hetkel Reaalse massiivi elementide kordamiseks on kolm võimalust:
  1. meetod Array.prototype.forEach ;
  2. klassikaline silmuse jaoks
  3. "õigesti" konstrueeritud ... in loop jaoks.
Lisaks on peagi, uue ECMAScript 6 (ES 6) standardi tulekuga oodata veel kahte meetodit:
  1. for...of loop (iteraatori kaudne kasutamine);
  2. iteraatori selgesõnaline kasutamine.

1. ForEach meetod ja sellega seotud meetodid

Kui teie projekt on loodud ECMAScript 5 (ES5) standardi funktsioonide toetamiseks, võite kasutada üht selle uuendustest – meetodit forEach.

Kasutusnäide:
var a = ["a", "b", "c"]; a.forEach(function(entry) ( console.log(entry); ));
Üldiselt nõuab forEachi kasutamine brauserite jaoks, millel seda pole, es5-shim emulatsiooniteegi ühendamist kohalik tugi seda meetodit. Nende hulka kuuluvad IE 8 ja uuemad varased versioonid, mis on siin-seal endiselt kasutusel.

ForEachi eeliseks on see, et praeguse massiivielemendi indeksi ja väärtuse salvestamiseks pole vaja deklareerida kohalikke muutujaid, kuna need edastatakse argumentidena automaatselt tagasihelistamisfunktsioonile.

Kui olete mures iga elemendi tagasihelistamise võimalike kulude pärast, ärge muretsege ja lugege seda.

ForEach on loodud kordama kõiki massiivi elemente, kuid lisaks sellele pakub ES5 veel mitmeid kasulikke meetodeid kõigi või mõne elemendi itereerimiseks ja nendega teatud toimingute tegemiseks:

  • every - tagastab tõene , kui iga massiivi elemendi jaoks tagastab tagasikutse väärtuse , mille saab teisendada tõeseks .
  • mõned – tagastab tõene, kui vähemalt ühe massiivi elemendi puhul tagastab tagasikutse väärtuse, mille saab teisendada tõeseks.
  • filter – loob uue massiivi, mis sisaldab neid algse massiivi elemente, mille puhul tagasihelistamine tagastab tõene.
  • kaart - loob uue massiivi, mis koosneb tagasihelistamisel tagastatud väärtustest.
  • vähenda – vähendab massiivi ühele väärtusele, rakendades igale massiivi elemendile kordamööda tagasihelistamist, alustades esimesest (võib olla kasulik massiivi elementide ja muude kokkuvõtlike funktsioonide summa arvutamisel).
  • ReductionRight – töötab sarnaselt vähendamisega, kuid kordab elemente vastupidises järjekorras.

2. Silmuse jaoks

Vana hea reeglite jaoks:

Var a = ["a", "b", "c"]; var indeks; jaoks (indeks = 0; indeks< a.length; ++index) { console.log(a); }
Kui massiivi pikkus on kogu tsükli vältel konstantne ja silmus ise kuulub koodi jõudluskriitilisse osasse (mis on ebatõenäoline), saate kasutada "optimaalsemat". versioon jaoks koos massiivi pikkuse salvestamisega:

Var a = ["a", "b", "c"]; var indeks, len; jaoks (indeks = 0, len = a.pikkus; indeks< len; ++index) { console.log(a); }
Teoreetiliselt peaks see kood jooksma veidi kiiremini kui eelmine.

Kui elementide järjekord pole oluline, saate optimeerimise osas veelgi kaugemale minna ja vabaneda massiivi pikkuse salvestamise muutujast, muutes otsingu järjekorra vastupidiseks:

Var a = ["a", "b", "c"]; var indeks; for (indeks = a.pikkus - 1; indeks >= 0; --indeks) ( console.log(a); )
Kaasaegsetes JavaScripti mootorites ei tähenda sellised optimeerimismängud aga tavaliselt midagi.

3. For...in loop õige kasutamine

Kui teile soovitatakse kasutada for...in tsüklit, pidage meeles, et massiivide itereerimine pole see, milleks see mõeldud pole. Vastupidiselt levinud eksiarvamusele ei kordu for...in tsükkel massiiviindeksite, vaid pigem objekti loendatavate omaduste kaudu.

Mõnel juhul, näiteks hõredate massiivide kordamine, võib for...in olla kasulik, kui võtate ettevaatusabinõusid, nagu on näidatud allolevas näites:

// a - hõre massiiv var a = ; a = "a"; a = "b"; a = "c"; for (var key in a) ( if (a.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && võti<= 4294967294) { console.log(a); } }
Selles näites tehakse tsükli igal iteratsioonil kaks kontrolli:

  1. et massiivil on oma omadus nimega võti (pole päritud selle prototüübilt).
  2. see võti on string, mis sisaldab täisarvu kümnendsüsteemi, mille väärtus on väiksem kui 4294967294. Kust pärineb viimane number? Massiiviindeksi definitsioonist ES5-s, mis näitab, et suurim indeks, mis massiivi elemendil võib olla, on: (2^32 - 2) = 4294967294 .
Loomulikult võtavad sellised kontrollid tsükli täitmisel tarbetult aega. Kuid hõreda massiivi korral on see meetod tõhusam kui for-silmus, kuna sel juhul itereeritakse ainult neid elemente, mis on massiivis selgelt määratletud. Seega tehakse ülaltoodud näites ainult 3 iteratsiooni (indeksite 0, 10 ja 10000 puhul) võrreldes 10001-ga for-tsüklis.

Et mitte kirjutada nii tülikat kontrollkoodi iga kord, kui peate massiivi läbima, saate selle kirjutada eraldi funktsioonina:

Funktsioon arrayHasOwnIndex(massiiv, võti) ( return array.hasOwnProperty(võti) && /^0$|^\d*$/.test(võti) && võti<= 4294967294; }
Siis väheneb näites oleva silmuse keha märkimisväärselt:

For (key in a) ( if (arrayHasOwnIndex(a, key)) ( console.log(a); ) )
Eespool käsitletud kontrollkood on universaalne, sobib kõikidel juhtudel. Kuid selle asemel võite kasutada lühemat versiooni, kuigi formaalselt mitte täiesti õige, kuid siiski sobib enamikul juhtudel:

For (võti sisse a) ( if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === võti) ( console.log(a); ) )

4. For...of loop (iteraatori kaudne kasutamine)

ES6, mis on endiselt mustandi olekus, peaks tutvustama iteraatoreid JavaScriptile.

Iteraator on protokoll, mida rakendab objekt, mis määratleb standardse viisi väärtuste jada (lõplik või lõpmatu) saamiseks.
Iteraator on objekt, mis määratleb next() meetodi – argumendita funktsiooni, mis tagastab kahe omadusega objekti:

  1. tehtud (tõeväärtus) – tõene, kui iteraator on jõudnud itereeritava jada lõppu. Vastasel juhul on väärtus vale.
  2. väärtus – määrab iteraatori tagastatud väärtuse. Võib olla defineerimata (puudub), kui tehtud omadus on tõene .
Paljud sisseehitatud objektid, sh. reaalsetel massiividel on vaikimisi iteraatorid. Lihtsaim viis iteraatori kasutamiseks reaalsetes massiivides on kasutada uut for...of konstruktsiooni.

Näide kasutamise kohta ... kohta:

Varval; var a = ["a", "b", "c"]; for (val of a) ( console.log(val); )
Ülaltoodud näites kutsub for...of tsükkel kaudselt välja massiivi objekti iteraatori, et saada massiivi iga väärtus.

5. Iteraatori selgesõnaline kasutamine

Iteraatoreid saab kasutada ka eksplitsiitselt, kuid sel juhul muutub kood palju keerulisemaks võrreldes for...of tsükliga. See näeb välja umbes selline:

Var a = ["a", "b", "c"]; var it = a.entries(); var kanne; while (!(entry = it.next()).done) ( console.log(entry.value); )
Selles näites tagastab meetod Array.prototype.entries iteraatori, mida kasutatakse massiivi väärtuste kuvamiseks. Igas iteratsioonis sisaldab enter.value massiivi kujul [võti, väärtus] .

II. Itereerimine massiivilaadsete objektide kohal

Lisaks päris massiividele on ka JavaScriptis olemas massiivilaadsed objektid . Reaalsete massiividega on neil ühist see, et neil on pikkusomadus ja omadused, mida nimetatakse massiivi elementidele vastavateks numbriteks. Näited hõlmavad NodeListi kollektsiooni DOM-i ja argumendid pseudomassiivi, mis on saadaval mis tahes funktsioonis/meetodis.

1. Reaalmassiivide iteratsiooni meetodite kasutamine

Vähemalt saab massiivilaadsete objektide itereerimiseks kasutada enamikku, kui mitte kõiki, reaalsete massiivide üle itereerimise meetodeid.

Konstruktsioone for ja for...in saab rakendada massiivilaadsetele objektidele täpselt samamoodi nagu päris massiividele.

ForEach ja teised Array.prototype meetodid kehtivad ka massiivilaadsete objektide puhul. Selleks peate kasutama funktsiooni Function.call või Function.apply .

Näiteks kui soovite rakendada forEach-i sõlmeobjekti atribuudile childNodes, tehke seda järgmiselt:

Array.prototype.forEach.call(node.childNodes, function(child) ( // tee alamobjektiga midagi));
Selle nipi taaskasutamise hõlbustamiseks võite deklareerida viite meetodile Array.prototype.forEach eraldi muutujas ja kasutada seda otseteena:

// (Eeldades, et kogu allolev kood on samas ulatuses) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // tee midagi alamobjektiga));
Kui massiivilaadsel objektil on iteraator, saab seda kasutada eksplitsiitselt või kaudselt objekti üle itereerimiseks samamoodi nagu päris massiivide puhul.

2. Teisenda reaalmassiiviks

Massiivilaadse objekti itereerimiseks on ka teine, väga lihtne viis: teisendage see reaalseks massiiviks ja kasutage reaalsete massiivide itereerimiseks mõnda ülalkirjeldatud meetodit. Teisendamiseks saate kasutada üldist meetodit Array.prototype.slice, mida saab rakendada mis tahes massiivilaadse objekti jaoks. Seda tehakse väga lihtsalt, nagu on näidatud allolevas näites:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
Näiteks kui soovite teisendada NodeListi kogu tegelikuks massiiviks, vajate midagi sellist:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);
Värskenda: Nagu kommentaarides märgitud

Massiivid on üks kõige sagedamini kasutatavaid muutujate tüüpe, mis võimaldavad salvestada palju järjestikuseid väärtusi "ühes kohas". JavaScripti osas on aga arenguruumi.

Selles artiklis vaatleme kolme vähetuntud tehnikat, mida saab kasutada massiividega töötamisel.

1. Massiividele kohandatud omaduste lisamine

Kui kasutate JavaScripti keeles massiivi definitsiooni leidmiseks otsingut, väidavad enamik allikaid, et seda tüüpi muutuja väärtust esitatakse objektina.

Üldiselt on paljud asjad, mida JavaScriptis kohtame, objektid. Oleks õiglane märkida, et keel sisaldab ka "primitiivseid" andmetüüpe, kuid nende väärtusi kasutatakse kuidagi objektide sees olevates omadustes.

2. Juurdepääs massiivi elementidele tsükli sees

Kuna massiiviindeksid võivad võtta ainult positiivseid väärtusi, algab loendamine nullist. Hiljem saame kasutada seda indeksit massiivi elemendile juurdepääsuks antud tsükli iteratsioonil.

ECMAScript6 tutvustas võimalust sirvida massiivi ilma indekseid kasutamata, vaid läbi uue for…of tsükli.

For...of silmus on loodud massiivi elementide itereerimiseks ilma elemendi indeksit mõjutamata.

Var ary = ["apelsin","õun","litši"]; for (let item of ary)( console.log(item); ) // "oranž", "õun", "litši" Võrdluseks: üksuseindeksite väljastamine for-tsüklis. var ary = ["apelsin","õun","litši"]; for (var item = 0; item< ary.length; item++){ console.log(item); } // 0, 1, 2

3. Elementide arv ei ole massiivi mõõde

Kui me räägime massiivi suurusest, peame seda tavaliselt sellesse salvestatud elementide arvuks. Tegelikult pole see täiesti tõsi – pikkuse omadus arvutatakse sõltuvalt elemendi maksimaalsest indeksist.

Pikkusomadus on väga mitmetähenduslik. Selle kontrollimiseks vaadake lihtsalt järgmisi manipuleerimisi:

Var ary = ; ary.length = 3; konsool.log(ary.length); // 3 ary = "abcd"; konsool.log(ary.length); // 6

Viimases näites piisas elemendi viiendale positsioonile panemisest, mille tulemusena sai massiivi pikkuseks 6. Kui arvate, et indeksid 0 kuni 4 luuakse automaatselt, siis eksite. Seda saab kontrollida operaatoriga in.

Var ary = ; ary.length = 3; konsool.log(ary.length); // 3 ary = "abcd"; konsool.log(ary.length); // 6 console.log(0 in ary); // vale

Sel juhul oleks õiglane nimetada aaria massiivi "hõredaks".

Samuti saame massiivide kärpimiseks manipuleerida pikkuse atribuudiga. Allolev näide demonstreerib elemendi "kaotamist" indeksi 5 juures, vähendades araari massiivi pikkuse omadust.

Var ary = ; ary.length = 3; konsool.log(ary.length); // 3 ary = "abcd"; konsool.log(ary.length); // 6 ary.length = 2; konsool.log(ary.length); // 2 console.log(ary); // määratlemata

Massiivid on programmeerimiskeeltes laialdaselt kasutatav andmetüüp, mida kasutatakse mitme väärtuse samaaegseks salvestamiseks. Kuid JavaScripti keele mõne aspekti spetsiifilisuse tõttu on massiividel mõned funktsioonid, mida sageli ei käsitleta. Selles postituses vaatlen kolme vähemtuntud, kuid siiski olulist JavaScripti massiivi funktsiooni, mille olemasolust te ei pruugi arugi saada...

Enne alustamist tahan märkida, et see tekst on loogiline jätk sarnasele postitusele - nii et järgige linki ja lugege :)

Kohandatud atribuutide lisamine massiividesse

Kui olete kunagi otsinud Internetist täielikku määratlust massiivid JavaScriptis, siis leiad suure tõenäosusega allikaid, kus on kirjas, et massiivid JavaScriptis on objektid ja ükskõik kui kummaliselt see ka ei kõlaks, on see tõsi.

Tegelikult peaaegu kõike, millega me tegeleme JavaScript on objekt. Põhimõtteliselt on kahte tüüpi andmed JavaScriptisprimitiivid Ja objektid, kuid primitiivid on alati mähitud objektide sisse.

Liikuge läbi massiivi elementide

Pärast selle alapealkirja lugemist mõtlesite arvatavasti - "Ei midagi uut - ma tean seda juba" ja teil on osaliselt õigus, sest igaüks, isegi algaja, võib massiivi elemente läbi vaadata, kuid tegelikult on see kõik üsna abstraktne ja tsükkel liigub läbi massiiviindeksite .

Alates massiivi indeksid koosnevad ainult mittenegatiivsetest täisarvudest, tsüklis "itereerime" täisarvu väärtust, alustades tavaliselt nullist ja lõpetades arvuga, mis tähistab massiivi suurust, ning seejärel kasutame "itereeritud" väärtust, et pääseda juurde massiivi elemendile. massiiv antud indeksis.

ECMAScript6-s on aga viis, kuidas saate massiivi väärtusi korrata, ilma indeksitele mõtlemata, ja saate seda teha for...of tsükliga.

Massiivis kordab for...of tsükkel massiivi elemente indeksi järjekorras, teisisõnu, te ei pea enam muretsema indeksite itereerimise ja olemasoleva hankimise pärast massiivi väärtused antud indeksi juures. For…of silmus on ideaalne, kui soovite lihtsalt massiivi elemente tsükliliselt väljastada ja nendega tööd alustada. Näiteks:

JavaScript

var arr = ["õun","banaan","apelsin"]; for (let item of arr)( console.log(item); ) // "õun","banaan","apelsin"

Võrdluseks vaatame nüüd standardne massiivisilmus väärtusindeksit selgesõnaliselt täpsustamata.

JavaScript

var arr = ["õun","banaan","apelsin"]; for (var item = 0; item< arr.length; item++){ console.log(item); } // 0, 1, 2

Elementide arv ei näita massiivi tegelikku suurust

Tavaliselt, kui räägime massiivi suurusest, peame seda kas arvuks, millel on massiivi väärtus, või suurusena, mille oleme massiivile käsitsi andnud. Samas tegelikkuses massiivi suurus sõltub selle suurimast olemasolevast indeksist.

Pikkus- (Ma tean, et seda nimetatakse üldiselt pikkuseks, kuid ma olen väga harjunud seda suuruseks nimetama, nii et andke andeks juba ette, kui kedagi eksitasin) - väga paindlik omadus. Kas olete massiivi suuruse juba eelnevalt fikseerinud või mitte, kui jätkate lisada massiivi väärtusi, selle suurus kasvab vastavalt. Näiteks:

JavaScript

var arr = ; arr.length = 3; konsool.log(arr.length); // 3 arr = "abcd"; konsool.log(arr.length); // 6

var arr = ;

arr. pikkus = 3;

// 3

arr [5] = "abcd";

konsool. log (arr . pikkus ) ;

// 6

Ülaltoodud näites näete, et andsin massiivile indeksi 5 juures ainult ühe väärtuse ja selle suuruseks sai 6. Kui nüüd arvate, et indeksi 5 juures väärtuse lisamisel lõi massiiv automaatselt indeksid vahemikus 0 kuni 4, siis kas sa eksid sügavalt. Selles massiivis pole tegelikult ühtegi indeksit vahemikus 0 kuni 4. Seda saate kontrollida operaatori in-i abil.

JavaScript

var arr = ; arr.length = 3; konsool.log(arr.length); // 3 arr = "abcd"; konsool.log(arr.length); // 6 console.log(0 in arr); // vale

var arr = ;

arr. pikkus = 3;

konsool. log (arr . pikkus ) ;

// 3

arr [5] = "abcd";

konsool. log (arr . pikkus ) ;