Para sa bawat array sa javascript?

Paano ko malalaman ang lahat ng mga entry sa isang array gamit ang javascript?

Akala ko ito ay ganito:

 forEach(instance in theArray) 

Saan theArray ang aking hanay, ngunit tila mali.

4041
17 февр. Itakda ang Dante1986 noong Pebrero 17 2012-02-17 16:51 '12 sa 04:51 2012-02-17 16:51
@ 32 mga sagot
  • 1
  • 2

Tl; DR

  • Huwag gumamit for-in kung hindi mo ito gagamitin ng proteksyon o, hindi bababa sa, hindi mo alam kung bakit ito ay maaaring kumagat sa iyo.
  • Ang iyong pinakamahusay na taya ay karaniwang

    • for-of loop (para lamang sa ES2015 +),
    • Array#forEach ( spec | MDN ) (o ang mga kamag-anak nito at some ) (ES5 + lamang)
    • simpleng lumang moderno for loop,
    • o for-in input na may proteksyon.

Ngunit mayroong pa rin ng maraming upang galugarin, basahin sa ...


Ang JavaScript ay may makapangyarihang semantika para sa cyclically pagbabago arrays at mga bagay ng array uri. Ibinahagi ko ang sagot sa dalawang bahagi: mga opsyon para sa mga tunay na array at mga pagpipilian para sa mga bagay na katulad lamang sa mga arrays, tulad ng mga arguments bagay, iba pang mga bagay na iterable (ES2015 +), mga koleksyon ng DOM, atbp.

Napansin ko agad na maaari mo na ngayong gamitin ang mga pagpipilian ES2015, kahit na sa ES5 engine, sa pamamagitan ng pagpapadala ng ES2015 sa ES5. Hanapin ang "ES2015 transpiling" / "ES6 transpiling" para sa higit pa ...

Well, tingnan ang aming mga pagpipilian:

Para sa mga tunay na arrays

Mayroon kang tatlong mga pagpipilian sa ECMAScript 5 ("ES5"), ang bersyon na pinakamalawak na sinusuportahan sa sandaling ito, at dalawa pang idinagdag sa ECMAScript 2015 ("ES2015", "ES6"):

  1. Gamitin forEach at mga kaugnay (ES5 +)
  2. Gumamit ng simple for loop
  3. Maayos na gamitin ang for-in
  4. Gamitin for-of (gamitin ang implicit iterator) (ES2015 +)
  5. Gamitin ang iterator nang tahasan (ES2015 +)

Mga Detalye:

1. Gamitin forEach at mga kaugnay

Sa anumang hindi makabagong kapaligiran sa kapaligiran (maayos, hindi sa IE8), kung saan mayroon kang access sa mga function ng Array idinagdag ng ES5 (direkta o gumagamit ng polyple fillings), maaari mong gamitin ang forEach ( spec | MDN ):

 var a = ["a", "b", "c"]; a.forEach(function(entry) { console.log(entry); }); 

forEach tumatanggap ng isang function ng callback at, opsyonal, isang halaga na ginamit tulad this kapag tinawag ang callback na ito (hindi ginagamit sa itaas). Ang callback ay tinatawag para sa bawat entry sa array upang laktawan ang mga di-umiiral na mga entry sa kalat arrays. Kahit na ginamit ko lamang ang isang argument sa itaas, ang callback ay tinatawag na may tatlong: ang halaga ng bawat rekord, ang index ng rekord na ito, at ang link sa array na iyong paulit-ulit (kung ang iyong function ay hindi na ito).

Kung hindi mo sinusuportahan ang mga browser ng legacy, tulad ng IE8 (kung saan ipinapakita ng NetApps sa higit sa 4% ng merkado sa panahon ng pagsulat na ito noong Setyembre 2016), maaari mong gamitin nang maligaya ang forEach sa bawat isang unibersal na pahina ng web na wa>forEach operasyon (hanapin ang "es5 shim" para sa i>

forEach ay may kalamangan na hindi mo kai>

Kung nag-aalala ka tungkol sa oras na kinakai>mga detalye

Bi>forEach ay isang "loop sa pamamagitan ng lahat ng mga ito" function, ngunit ES5 ay tinukoy ng i>

  • every (hihinto ang loop sa unang pagkakataon ang callback ay nagbabalik ng false o isang bagay na hindi totoo)
  • some (tumitigil sa loop sa unang pagkakataon ang callback ay bumalik true o isang bagay na maaaring totoo)
  • filter (lumilikha ng isang bagong array na kinabibi>true at umaalis sa mga kung saan ito ay nagbabalik ng false )
  • map (lumilikha ng isang bagong hanay ng mga return callback value)
  • reduce (palugit ang isang halaga, muling tumatawag sa isang callback, pagpasa sa nakaraang mga halaga, tingnan ang detalye para sa mga detalye, kapaki-pakinabang para sa pagbubuod ng mga nilalaman ng isang array at maraming iba pang mga bagay)
  • reduceRight (halimbawa, reduce , ngunit gumagana sa pababang pagkakasunud-sunod, hindi sa pataas na pagkakasunud-sunod)

2. Gumamit ng isang simpleng for loop

Kung minsan ang mga lumang paraan ay pinakamahusay:

 var index; var a = ["a", "b", "c"]; for (index = 0; index < a.length; ++index) { console.log(a[index]); } 

Kung ang haba ng array ay hindi nagbabago sa panahon ng pag-ikot, at ang pagganap nito ay sensitibong code (malamang na hindi), ang isang bahagyang mas kumplikadong bersyon ng makunan na may haba ng harap ay maaaring maging kaunti nang mas mabilis:

 var index, len; var a = ["a", "b", "c"]; for (index = 0, len = a.length; index < len; ++index) { console.log(a[index]); } 

At / o pagbibi>

 var index; var a = ["a", "b", "c"]; for (index = a.length - 1; index >= 0; --index) { console.log(a[index]); } 

Ngunit sa modernong mga JavaScript na mekanismo, bihira kang kai>

Sa ES2015 at mas mataas, maaari mong gawin ang iyong mga index at halaga ng mga variable lokal for for loop:

 let a = ["a", "b", "c"]; for (let index = 0; index < a.length; ++index) { let value = a[index]; } //console.log(index); // Would cause "ReferenceError: index is not defined" //console.log(value); // Would cause "ReferenceError: value is not defined" 

At kapag ginawa mo ito, hindi lamang ang value kundi pati na rin ang index muling ginawa para sa bawat pag-ulit ng loop, ibig sabihin, ang mga pagsasara na nilikha sa loop tag ay naglalaman ng isang reference sa index (at value ) na nilikha para sa partikular na pag-ulit:

 let divs = document.querySelectorAll("div"); for (let index = 0; index < divs.length; ++index) { divs[index].addEventListener('click', e => { alert("Index is: " + index); }); } 

Kung mayroon kang limang divs, makakakuha ka ng "Index ay: 0", kung na-click mo ang una at "Index ay: 4", kung na-click mo ang huling. Hindi ito gumagana kung gumamit ka ng var halip na let .

3. Gamitin nang wasto.

Makakakuha ka ng mga tao na nagsasabi sa iyo na gamitin for-in , ngunit ito ay hindi kung ano ang for-in para sa . for-in nakasulat sa pamamagitan ng enumerated properties ng bagay, at hindi ang mga indeks ng array. Ang order ay hindi garantisadong , kahit sa ES2015 (ES6). Tinutukoy ng ES2015 ang pagkakasunud-sunod ng mga katangian ng isang bagay (gamit ang [[OwnPropertyKeys]] , [[Enumerate]] , at mga bagay na gumagamit nito bi>Object.getOwnPropertyKeys ), ngunit hindi ito tumutukoy na ang for-in ay susundin ang utos na iyon. (Mga detalye sa iba pang sagot na ito .)

Gayunpaman, ito ay maaaring maging kapaki-pakinabang, lalo na para sa mga kalat - kalat arrays , kung gumamit ka ng naaangkop na pag-iingat:

 // 'a' is a sparse array var key; var a = []; a[0] = "a"; a[10] = "b"; a[10000] = "c"; for (key in a) { if (a.hasOwnProperty(key)  // These are explained /^0$|^[1-9]\d*$/.test(key)  // and then hidden key <= 4294967294 // away below ) { console.log(a[key]); } } 

Tandaan ang dalawang tseke:

  1. Na ang bagay ay may sariling ari-arian sa ilalim ng panga>

  2. Na ang susi ay isang base-10 na numeric na string sa karaniwang string form nito, at ang halaga nito ay <= 2 ^ 32 - 2 (na 4,294,967,294). Saan nagmula ang numerong ito? Ito ay bahagi ng kahulugan ng array ng index sa detalye . Ang ibang mga numero (mga di-integer na numero, mga negatibong numero, mga numero na mas malaki kaysa sa 2 ^ 32 - 2) ay hindi mga indeks ng array. Ang dahilan ng 2 ^ 32-2 ay kung bakit ang pinakamataas na halaga ng index na mas mababa sa 2 ^ 32-1, na siyang pinakamataas na halaga ng length array. (Halimbawa, ang haba ng array ay tumutugma sa isang 32-bit na unsigned na integer.) (Isang kumpirmasyon mula sa RobG upang ipahiwatig sa isang komento sa aking blog post na ang aking nakaraang pagsubok ay hindi tama).

Ito ay isang maliit na bit ng karagdagang overhead para sa bawat pag-ulit ng mga loop sa karamihan ng mga array, ngunit kung mayroon kang isang kalat-kalat array, maaaring ito ay isang mas mahusay na paraan upang loop, dahil ang mga ito ay mga loop lamang para sa mga tala na aktwal na umiiral. Halimbawa, para sa array sa itaas, nakikipag loop kami ng tatlong beses (para sa mga key na "0" , "10" at "10000" - tandaan, ang mga ito ay mga linya), at hindi 10,001 beses.

Ngayon hindi mo nais na isulat ito sa bawat oras, upang maaari mong ilagay ito sa iyong toolkit:

 function arrayHasOwnIndex(array, prop) { return array.hasOwnProperty(prop)  /^0$|^[1-9]\d*$/.test(prop)  prop <= 4294967294; // 2^32 - 2 } 

At pagkatapos ay gagamitin namin ito tulad nito:

 for (key in a) { if (arrayHasOwnIndex(a, key)) { console.log(a[key]); } } 

O, kung ikaw ay interesado lamang sa pagsusulit na "sapat na mabuti para sa karamihan ng mga kaso", maaari mo itong gamitin, ngunit hangga't ito ay malapit na, ito ay hindi pa tama:

 for (key in a) { // "Good enough" for most cases if (String(parseInt(key, 10)) === key  a.hasOwnProperty(key)) { console.log(a[key]); } } 

4. Gumamit ng for-of (gamitin ang implicit iterator) (ES2015 +)

Nagdagdag ang ES2015 ng mga iterator sa JavaScript. Ang pinakamadaling paraan upang magamit ang mga iterators ay ang bagong for-of operator. Mukhang ito:

 var val; var a = ["a", "b", "c"]; for (val of a) { console.log(val); } 

Konklusyon:

 a b c

Sa ilalim ng mga pabalat, na nakakakuha ng isang iterator mula sa array at pumasa sa pamamagitan nito, nakakakuha ng mga halaga mula dito. Ito ay wa>for-in , sapagkat gumagamit ito ng isang iterator na tinukoy ng isang bagay (array), at ang mga arrays ay tinutukoy na ang kani>for-in sa ES5, ang pagkakasunud-sunod kung saan ang mga talaan ay tiningnan ay ang numerical order ng kani>

5. Gamitin ang iterator nang tahasan (ES2015 +)

Minsan maaari mong tahasang gamitin ang isang iterator. Maaari mo ring gawin ito, bagaman ito ay mas clunkier kaysa for-of . Mukhang ito:

 var a = ["a", "b", "c"]; var it = a.values(); var entry; while (!(entry = it.next()).done) { console.log(entry.value); } 

Ang iterator ay isang bagay na tumutugma sa kahulugan ng Iterator sa detalye. Ang kanyang next paraan ay nagbabalik ng isang bagong bagay na resulta tuwing tinatawag mo ito. Ang resulta ng bagay ay may ari-arian, done , nagsasabi sa amin kung tapos na ito, at ang value ari value arian na may halaga para sa pag-ulit na ito. ( done opsyonal kung ito ay false , ang value ay opsyonal kung hindi ito undefined ).

Ang value iiba depende sa iterator; arrays support (hindi bababa sa) tatlong mga function na bumalik iterators:

  • values() : Ito ang ginamit ko sa itaas. Nagbabalik ang iterator, kung saan ang bawat value ay isang talaan ng array para sa pag-ulit ( "a" , "b" at "c" sa halimbawa sa itaas).
  • keys() : Ibinabalik ang isang iterator, kung saan ang bawat value ay ang susi para sa pag-ulit (kaya para sa atin sa itaas, magkakaroon a "0" , at pagkatapos ay "1" , at pagkatapos ay "2" ).
  • entries() : nagbabalik ng isang iterator, kung saan ang bawat value ay isang array sa anyo ng [key, value] para sa pag-ulit na ito.

Para sa mga bagay tulad ng isang array

Bi>length ari-arian at mga ari-arian na may mga numerong pangalan: Mga pagkakataon sa NodeList , isang arguments bagay, atbp. Paano namin NodeList kani>

Gamitin ang alinman sa mga parameter sa itaas para sa mga arrays.

Hindi bababa sa ilan, at marahil karamihan o kahit na ang lahat ng mga nasa itaas na arrays ay madalas na ginagamit nang pantay na rin para sa mga bagay ng uri ng array:

  1. Gamitin forEach at mga kaugnay (ES5 +)

    Ang iba't ibang mga function sa Array.prototype ay "sadyang generic" at kadalasang magagamit para sa mga bagay tulad ng isang array sa pamamagitan ng Function#call Function#apply o Function#apply . (Tingnan ang Disclaimer para sa mga bagay na ibinigay ng host sa pagtatapos ng tugon na ito, ngunit ito ay isang pambihirang problema.)

    Ipagpalagay na nais mong gamitin ang forEach sa forEach Node childNodes . Gagawin mo ito:

     Array.prototype.forEach.call(node.childNodes, function(child) { // Do something with 'child' }); 

    Kung gagawin mo ito ng maraming, maaaring gusto mong makakuha ng isang kopya ng sanggunian sa pag-andar sa isang variable upang magamit muli, halimbawa:

     // (This is all presumably in some scoping function) var forEach = Array.prototype.forEach; // Then later... forEach.call(node.childNodes, function(child) { // Do something with 'child' }); 
  2. Gumamit ng simple for loop

    Maliwanag, ang isang simpleng for loop ay inilapat sa mga bagay tulad ng isang array.

  3. Maayos na gamitin ang for-in

    for-in may parehong mga garantiya tulad ng sa isang array, dapat gumana sa mga bagay na katulad ng isang array; Maaaring kai>

  4. Gamitin for-of (gamitin ang implicit iterator) (ES2015 +)

    for-of ay gagamit ng iterator na ibinigay ng bagay (kung mayroon man); dapat nating makita kung paano ito nangyayari sa iba't ibang mga bagay tulad ng array, lalo na sa mga file ng host. Halimbawa, ang pagtutukoy para sa NodeList mula sa querySelectorAll -update upang suportahan ang pag-ulit. Ang pagtutukoy para sa HTMLCollection ng getElementsByTagName hindi.

  5. Gamitin ang iterator nang tahasan (ES2015 +)

    Tingnan ang numero 4, kai>

Lumikha ng isang tunay na array

Sa iba pang mga kaso, maaari mong i-convert ang isang bagay tulad ng isang array sa isang tunay na array. Upang gawin ito ay nakakagulat na madali:

  1. Gamitin ang slice array method

    Maaari naming gamitin ang slice array na paraan, kung saan, tulad ng iba pang mga pamamaraan na binanggit sa itaas, ay "sadyang pangkaraniwang" at samakatuwid ay maaaring gamitin sa mga array na tulad ng mga bagay, halimbawa:

     var trueArray = Array.prototype.slice.call(arrayLikeObject); 

    Kaya, halimbawa, kung nais naming i-convert ang isang NodeList sa isang tunay na array, maaari naming gawin ito:

     var divs = Array.prototype.slice.call(document.querySelectorAll("div")); 

    Tingnan ang "Mag-ingat sa mga bagay na ibinigay ng host" sa ibaba. Sa partikular, tandaan na hindi ito gagana sa IE8 at mas maaga, na hindi pinapayagan ang paggamit ng mga bagay na ibinigay ng host na tulad this .

  2. Gumamit ng pamamahagi ng syntax ( ... )

    Posible ring gamitin ang ES2015 na pamamahagi ng syntax na may mga JavaScript na mekanismo na sumusuporta sa tampok na ito:

     var trueArray = [...iterableObject]; 

    Kaya, halimbawa, kung nais naming i-convert ang isang NodeList sa isang totoong array, kasama ang syntax ng pagpapalaganap, nagiging NodeList ito:

     var divs = [...document.querySelectorAll("div")]; 
  3. Gumamit ng Array.from (spec) | (MDN)

    Array.from (ES2015 +, ngunit madaling poly na puno) ay lumilikha ng isang array mula sa isang bagay tulad ng isang array, kung kinakai>

     var divs = Array.from(document.querySelectorAll("div")); 

    O, kung nais mong makakuha ng isang hanay ng mga pangalan ng tag para sa mga elemento na may isang ibinigay na klase, dapat mong gamitin ang pag-andar ng pagma-map:

     // Arrow function (ES2015): var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName); // Standard function (since 'Array.from' can be shimmed): var divs = Array.from(document.querySelectorAll(".some-class"), function(element) { return element.tagName; }); 

Mag-ingat sa mga pasilidad na ibinigay ng host

Kung gumamit Array.prototype function na Array.prototype may mga bagay tulad ng mga host (mga listahan ng DOM at iba pang mga bagay na ibinigay ng browser, sa halip na ang JavaScript engine), kai>Karamihan sa kanila ay kumikilos nang wasto (ngayon), ngunit mahalagang suriin. Ang dahilan dito ay ang karamihan sa mga pamamaraan ng Array.prototype maaaring gusto mong gamitin ay umaasa sa bagay na ibinigay ng host, na nagbibigay ng matapat na sagot sa abstract [[HasProperty]] . Sa panahon ng pagsulat na ito, ang mga browser ay gumawa ng isang napakahusay na trabaho sa mga ito, ngunit ang 5.1 specification iminungkahing na ang bagay na ibinigay ng host ay maaaring hindi patas. Ito ay nasa §8.6.2 , ng i>

Ang mga bagay ng host ay maaaring magpatupad ng mga panloob na pamamaraan sa anumang paraan maliban kung nabanggit; halimbawa, ang isang posibilidad ay ang [[Get]] at [[Put]] para sa isang partikular na bagay ng host ay talagang kunin at i-save ang mga halaga ng ari-arian, ngunit ang [[HasProperty]] laging gumagawa ng hindi totoo .

(Hindi ko mahanap ang isang katumbas na salita sa pagtutukoy ES2015, ngunit dapat pa rin.) Muli, tulad ng pagsulat ng isang karaniwang host ng ibinigay na array ng uri ng bagay sa mga modernong browser [Halimbawa ng NodeList , halimbawa], gawing tama ang [[HasProperty]] , ngunit mahalaga suriin.)

6292
17 февр. Ang sagot ay ibinigay ni TJ Crowder Pebrero 17. 2012-02-17 16:53 '12 sa 4:53 ng umaga 2012-02-17 16:53

I-edit : ang sagot na ito ay wa>pamamaraan na magagamit sa array . Ang mga pamamaraan ng interes ay maaaring:

  • para sa bawat isa
  • card
  • ang filter
  • zip fastener
  • upang mabawasan
  • bawat isa
  • kaunti

Ang karaniwang paraan upang maulit ang isang array sa JavaScript ay for -loop vanilla:

border=0
 var length = arr.length, element = null; for (var i = 0; i < length; i++) { element = arr[i]; // Do something with element } 

Tandaan, gayunpaman, na ang diskarte na ito ay mabuti lamang kung mayroon kang isang makakapal na array, at ang bawat indeks ay ginagawa ng isang elemento. Kung ang array ay kalat-kalat, pagkatapos ay sa diskarte na ito maaari kang tumakbo sa mga problema sa pagganap, dahil ikaw ay pumunta sa pamamagitan ng maraming mga index na talagang hindi umiiral sa array. Sa kasong ito, ito ay mas mahusay na gamitin for.. in -loop. Gayunpaman, dapat kang gumamit ng mga angkop na pag-iingat upang matiyak na ang mga kinakai>for..in , dahil para sa for..in -loop ay nakalista din sa mga legacy na browser, o kung ang karagdagang mga katangian ay tinukoy bi>enumerable .

Sa ECMAScript 5 , ang forEach na paraan ay gagamitin para sa array prototype, ngunit hindi ito sinusuportahan sa legacy browser. Samakatuwid, upang magamit ito nang tuloy-tuloy, dapat kang magkaroon ng kapaligiran na sumusuporta dito (halimbawa, Node.js para sa JavaScript ng server-side), o gamitin ang "Polyfill". Ang Polyfill para sa pag-andar na ito, gayunpaman, ay wa>

470
17 февр. Sumagot na ibinigay ng PatrikAkerstrand noong Pebrero 17. 2012-02-17 16:55 '12 sa 4:55 pm 2012-02-17 16:55

Kung gumagamit ka ng jQuery library, maaari mong gamitin ang jQuery.each :

 var length = yourArray.length; for (var i = 0; i < length; i++) { // Do something with yourArray[i]. } 
214
17 февр. Ang sagot ay ibinigay Poonam Pebrero 17. 2012-02-17 17:01 '12 sa 17:01 2012-02-17 17:01

Umikot pabalik

Sa tingin ko ang reverse para sa ikot ng takbo ay nararapat na banggitin dito:

 for (var i = array.length; i--; ) { // process array[i] } 

Mga Benepisyo:

  • Hindi mo kai>len o ihambing ito sa array.length sa bawat pag-ulit, na maaaring minutong pag-optimize.
  • Ang pag-aalis ng mga kapatid mula sa DOM sa reverse order ay karaniwang mas mahusay . (Kai>
  • Kung binago mo ang isang array sa isang loop, sa o pagkatapos ng isang index ko (halimbawa, tinanggal mo o ipasok ang isang elemento sa array[i] ), pagkatapos ay direktang loop ay mag-skips sa isang elemento na lumipat sa kaliwa upang iposisyon ko o susuriin ang i-ika na elemento na inilipat sa kanan. Sa tradisyunal na loop, maaari mong i-update ang i upang ituro sa susunod na elemento na kai>simple at mas eleganteng solusyon .
  • Katulad nito, kapag binabago o tinatanggal ang mga elemento ng nested DOM, ang pag-reverse ng pagproseso ay maaaring mag- bypass ng mga error . Halimbawa, isaa>
  • mas maikli at magbasa kaysa sa ibang mga opsyon na magagamit. Kahit na ito loses sa forEach() at sa ES6 for ... of .

Mga disadvantages:

  • Pinoproseso nito ang mga item sa reverse order. Kung nagtayo ka ng isang bagong hanay ng mga resulta o naka-print sa screen, ang output ay siyempre kanselahin kamag-anak sa orihinal na order.
  • Неоднократно вставляя братьев и сестер в DOM в качестве первого ребенка, чтобы сохранить их порядок, менее эффективен . (В браузере все равно придется перекладывать вещи.) Чтобы создавать узлы DOM эффективно и упорядоченно, просто переходите вперед и добавьте как обычно (а также используйте "фрагмент документа" ).
  • Обратный цикл запутывает для младших разработчиков. (Вы можете считать это преимущество, в зависимости от вашего прогноза.)

Должен ли я всегда использовать его?