Javascript kung paano makakuha ng mga elemento ng magulang. Mga diskarte sa DOM: mga elemento ng magulang, anak at kapitbahay. Pag-iwas sa Mga Default na Pagkilos

Ang forEach() pamamaraan ay nagpapatupad ng isang ibinigay na function nang isang beses para sa bawat elemento ng array.

Ang pinagmulan para sa interactive na halimbawang ito ay naka-imbak sa isang GitHub repository. Kung gusto mong mag-ambag sa proyekto ng mga interactive na halimbawa, paki-clone ang https://github.com/mdn/interactive-examples at padalhan kami ng pull request.

Syntax

arr .forEach(callback(currentValue [, index [, array]]) [, thisArg ])

Mga Parameter

callback Function na isagawa sa bawat elemento. Tumatanggap ito sa pagitan ng isa at tatlong argumento: currentValue Ang kasalukuyang elementong pinoproseso sa array. index Opsyonal Ang index currentValue sa array. array Opsyonal Ang array forEach() ay tinawag. thisArg Optional Value na gagamitin bilang ganito kapag nagsasagawa ng callback .

Ibalik ang halaga

Paglalarawan

Ang forEach() ay tumatawag ng ibinigay na function ng callback nang isang beses para sa bawat elemento sa isang array sa pataas na pagkakasunud-sunod. Hindi ito hinihingi para sa mga katangian ng index na natanggal o hindi nasimulan. (Para sa mga kalat-kalat na array, .)

Ang callback ay hinihingi ng tatlong argumento:

  1. ang halaga ng elemento
  2. ang index ng elemento
  3. ang Array object na dinadaanan

Kung ang isang thisArg na parameter ay ibinigay sa forEach() , ito ay gagamitin bilang callback na halagang ito. Ang thisArg na halaga ay sa huli ay mapapansin sa pamamagitan ng callback ay tinutukoy ayon sa karaniwang mga panuntunan para sa pagtukoy ng ito na nakikita ng isang function .

Ang hanay ng mga elementong naproseso ng forEach() ay itinakda bago ang unang invocation ng callback . Ang mga elemento na idinagdag sa array pagkatapos magsimula ang tawag sa forEach() ay hindi bibisitahin ng callback . Kung ang mga umiiral na elemento ng array ay binago o tinanggal, ang kanilang halaga bilang ipinasa sa callback ay ang halaga sa oras na binisita sila ng bawat(); Ang mga elemento na tinanggal bago bisitahin ay hindi binibisita. Kung ang mga elementong nabisita na ay aalisin (hal. gamit ang shift()) sa panahon ng pag-ulit, ang mga susunod na elemento ay lalaktawan. (Tingnan ang halimbawang ito, sa ibaba.)

forEach() ay nagpapatupad ng callback function nang isang beses para sa bawat elemento ng array; hindi tulad ng map() o reduce() palagi nitong ibinabalik ang value na hindi natukoy at hindi chainable. Ang karaniwang kaso ng paggamit ay ang magsagawa ng mga side effect sa dulo ng isang chain.

forEach() ay hindi mutate ang array kung saan ito ay tinatawag. (Gayunpaman, maaaring gawin ito ng callback)

Walang paraan upang ihinto o masira ang isang forEach() loop maliban sa pamamagitan ng paghagis ng exception. Kung kailangan mo ng ganoong pag-uugali, ang paraang forEach() ay ang maling tool.

Ang maagang pagwawakas ay maaaring magawa sa:

Mga pamamaraan ng array: every() , some() , find() , at findIndex() subukan ang array elements na may predicate na nagbabalik ng truthy value para matukoy kung kailangan ng karagdagang pag-ulit.

Mga halimbawa

Walang operasyon para sa mga hindi nasimulang halaga (mga kalat-kalat na array)

const arraySparse = let numCallbackRuns = 0 arraySparse.forEach(function(element)( console.log(element) numCallbackRuns++ )) console.log("numCallbackRuns: ", numCallbackRuns) // 1 // 3 // 7 // numCallbackRuns: 3 // komento: dahil nakikita mo ang nawawalang halaga sa pagitan ng 3 at 7 ay hindi nag-invoke ng callback function.

Pag-convert ng for loop sa forEach

const item = ["item1", "item2", "item3"] const copy = // bago para sa (hayaan i = 0; i< items.length; i++) { copy.push(items[i]) } // after items.forEach(function(item){ copy.push(item) })

Pag-print ng mga nilalaman ng isang array

Tandaan: Upang maipakita ang nilalaman ng isang array sa console, maaari mong gamitin ang console.table() , na nagpi-print ng naka-format na bersyon ng array.

Ang sumusunod na halimbawa ay naglalarawan ng alternatibong diskarte, gamit ang forEach() .

Ang sumusunod na code ay nag-log ng isang linya para sa bawat elemento sa isang array:

Function logArrayElements(element, index, array) ( console.log("a[" + index + "] = " + element) ) // Pansinin na ang index 2 ay nilaktawan, dahil walang item sa // na posisyon sa array... .forEach(logArrayElements) // logs: // a = 2 // a = 5 // a = 9

Gamit ang Arg na ito

Ang sumusunod na (nagawa) halimbawa ay nag-a-update ng mga katangian ng isang bagay mula sa bawat entry sa array:

Function Counter() ( this.sum = 0 this.count = 0 ) Counter.prototype.add = function(array) ( array.forEach(function(entry) ( this.sum += entry ++this.count ), ito ) // ^---- Tandaan ) const obj = new Counter() obj.add() obj.count // 3 obj.sum // 16

Dahil ang thisArg parameter (this) ay ibinibigay sa forEach() , ito ay ipinapasa sa callback sa tuwing ito ay i-invoke. Ginagamit ito ng callback bilang ang halaga nito.

Isang function ng pagkopya ng object

Ang sumusunod na code ay lumilikha ng isang kopya ng isang ibinigay na bagay.

Mayroong iba't ibang mga paraan upang lumikha ng isang kopya ng isang bagay. Ang sumusunod ay isang paraan lamang at ipinakita upang ipaliwanag kung paano gumagana ang Array.prototype.forEach() sa pamamagitan ng paggamit ng ECMAScript 5 Object.* meta property functions.

Function copy(obj) ( const copy = Object.create(Object.getPrototypeOf(obj)) const propNames = Object.getOwnPropertyNames(obj) propNames.forEach(function(name) ( const desc = Object.getOwnPropertyDescriptor(obj, name) Object .defineProperty(copy, name, desc) )) return copy ) const obj1 = ( a: 1, b: 2 ) const obj2 = copy(obj1) // obj2 parang obj1 ngayon

Kung ang array ay binago sa panahon ng pag-ulit, ang iba pang mga elemento ay maaaring laktawan.

Ang sumusunod na halimbawa ay nag-log "isa" , "dalawa" , "apat" .

Kapag ang entry na naglalaman ng value na "two" is reached, the first entry of the whole array is shifted off-resulting in all remaining entries moving up one position. Because element "four" is now at an earlier position in the array, "three" will be skipped.!}

forEach() ay hindi gumagawa ng kopya ng array bago umulit.

Hayaan ang mga salita = ["isa", "dalawa", "tatlo", "apat"] na salita.forEach(function(word) ( console.log(word) if (salita === "dalawa") ( words.shift( ) ) )) // isa // dalawa // apat

I-flatte ang isang array

Ang sumusunod na halimbawa ay narito lamang para sa layunin ng pag-aaral. Kung gusto mong i-flatten ang isang array gamit ang mga built-in na pamamaraan maaari mong gamitin ang Array.prototype.flat() (na inaasahang magiging bahagi ng ES2019, at ipinapatupad na sa ilang browser).

/** * Mga flatten ang pumasa sa array sa isang dimensional array * * @params (array) arr * @returns (array) */ function flatten(arr) ( const result = arr.forEach((i) => ( if (Array. isArray(i)) ( result.push(...flatten(i)) ) else ( result.push(i) )) return result ) // Problema sa const ng paggamit = , 8, 9]] flatten(problema) / /

Tandaan sa paggamit ng Mga Pangako o async function

let ratings = let sum = 0 let sumFunction = async function (a, b) ( return a + b ) ratings.forEach(async function(rating) ( sum = await sumFunction(sum, rating) )) console.log(sum) // Inaasahang output: 14 // Aktwal na output: 0

Mga pagtutukoy

Pagtutukoy Katayuan Magkomento
Pinakabagong Draft ng ECMAScript (ECMA-262)
Draft
ECMAScript 2015 (6th Edition, ECMA-262)
Ang kahulugan ng "Array.prototype.forEach" sa detalyeng iyon.
Pamantayan
ECMAScript 5.1 (ECMA-262)
Ang kahulugan ng "Array.prototype.forEach" sa detalyeng iyon.
Pamantayan Paunang kahulugan. Ipinatupad sa JavaScript 1.6.

Pagkatugma sa browser

Ang talahanayan ng compatibility sa page na ito ay nabuo mula sa structured data. Kung gusto mong mag-ambag sa data, pakitingnan ang https://github.com/mdn/browser-compat-data at padalhan kami ng pull request.

I-update ang data ng compatibility sa GitHub

DesktopMobileserver
ChromegilidFirefoxInternet ExplorerOperaSafariAndroid webviewChrome para sa AndroidFirefox para sa AndroidOpera para sa AndroidSafari sa iOSSamsung InternetNode.js
para sa bawatChrome Buong suporta 1Edge Buong suporta 12Buong suporta ng Firefox 1.5IE Buong suporta 9Opera Buong suporta OoSafari Buong suporta 3WebView Android Buong suporta ≤37Chrome Android Buong suporta 18Firefox Android Buong suporta 4Opera Android Buong suporta OoSafari iOS Buong suporta 1Samsung Internet Android Buong suporta 1.0nodejs Buong suporta Oo
  • I. Pag-ulit sa mga totoong array
    1. para sa bawat pamamaraan at mga kaugnay na pamamaraan
    2. para sa loop
    3. Wastong paggamit ng for...in loop
    4. para sa...ng loop (implicit na paggamit ng iterator)
    5. Tahasang paggamit ng iterator
  • II. Pag-ulit sa mga bagay na tulad ng array
    1. Gumagamit ng mga pamamaraan upang umulit sa mga totoong array
    2. I-convert sa isang tunay na array
    3. Isang tala sa mga bagay sa runtime

I. Pag-ulit sa mga totoong array

Sa ngayon, may tatlong paraan upang umulit sa mga elemento ng isang tunay na array:

  1. paraan Array.prototype.forEach ;
  2. classic para sa loop
  3. isang "tama" na binuo para sa...in loop.

Bilang karagdagan, sa lalong madaling panahon, sa pagdating ng bagong ECMAScript 6 (ES 6) na pamantayan, dalawa pang pamamaraan ang inaasahan:

  1. para sa...ng loop (implicit na paggamit ng iterator);
  2. tahasang paggamit ng iterator.

1. Ang para sa bawat pamamaraan at mga kaugnay na pamamaraan

Kung ang iyong proyekto ay idinisenyo upang suportahan ang mga tampok ng pamantayan ng ECMAScript 5 (ES5), maaari mong gamitin ang isa sa mga inobasyon nito - ang paraang para sa bawat.

Halimbawa ng paggamit:

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

Sa pangkalahatan, ang paggamit ng forEach ay nangangailangan ng pagkonekta sa es5-shim emulation library para sa mga browser na hindi katutubong sumusuporta sa paraang ito. Kabilang dito ang IE 8 at mas maaga, na ginagamit pa rin sa ilang lugar.

Ang bentahe ng forEach ay hindi na kailangang magdeklara ng mga lokal na variable upang iimbak ang index at halaga ng kasalukuyang elemento ng array, dahil awtomatiko silang ipinapasa sa function ng callback bilang mga argumento.

Kung nag-aalala ka tungkol sa posibleng gastos sa pagtawag ng callback sa bawat elemento, huwag mag-alala at basahin ito.

Ang forEach ay idinisenyo upang umulit sa lahat ng mga elemento ng isang array, ngunit bukod dito, ang ES5 ay nag-aalok ng ilang mas kapaki-pakinabang na pamamaraan para sa pag-ulit sa lahat o ilang mga elemento at pagsasagawa ng ilang mga aksyon sa mga ito:

  • every - nagbabalik ng true kung para sa bawat elemento ng array ang callback ay nagbabalik ng value na maaaring ma-convert sa true.
  • some - nagbabalik ng true kung para sa hindi bababa sa isang elemento ng array ang callback ay nagbabalik ng isang halaga na maaaring ma-convert sa true.
  • filter - lumilikha ng bagong array na kinabibilangan ng mga elemento ng orihinal na array kung saan ang callback ay nagbabalik ng true .
  • mapa - lumilikha ng isang bagong array na binubuo ng mga halaga na ibinalik ng callback.
  • bawasan - binabawasan ang isang array sa isang solong halaga, paglalapat ng isang callback sa bawat elemento ng array, simula sa una (maaaring maging kapaki-pakinabang para sa pagkalkula ng kabuuan ng mga elemento ng array at iba pang mga function ng buod).
  • reduceRight - gumagana katulad ng pagbabawas, ngunit umuulit sa pamamagitan ng mga elemento sa reverse order.

2. Para sa loop

Mabuting gulang para sa mga patakaran:

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

Kung ang haba ng array ay pare-pareho sa buong loop, at ang loop mismo ay kabilang sa isang performance-critical na seksyon ng code (na hindi malamang), maaari kang gumamit ng "mas pinakamainam" na bersyon ng para na nag-iimbak ng haba ng array :

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

Sa teorya, ang code na ito ay dapat tumakbo nang mas mabilis kaysa sa nauna.

Kung ang pagkakasunud-sunod ng mga elemento ay hindi mahalaga, maaari kang pumunta nang higit pa sa mga tuntunin ng pag-optimize at alisin ang variable para sa pag-iimbak ng haba ng array, pagbabago ng pagkakasunud-sunod ng paghahanap sa reverse:

Var a = ["a", "b", "c"]; var index; para sa (index = a.length - 1; index >= 0; --index) ( console.log(a); )

Gayunpaman, sa mga modernong JavaScript engine, ang ganitong mga laro sa pag-optimize ay karaniwang walang kahulugan.

3. Tamang paggamit ng for...in loop

Kung pinapayuhan kang gumamit ng for...in loop, tandaan na ang pag-ulit sa mga array ay hindi para sa layunin nito. Taliwas sa isang karaniwang maling kuru-kuro, ang for...in loop ay hindi umuulit sa mga indeks ng array, ngunit sa halip ay sa pamamagitan ng enumerable na katangian ng isang bagay.

Gayunpaman, sa ilang mga kaso, tulad ng pag-ulit sa mga kalat-kalat na array, para...in ay maaaring maging kapaki-pakinabang, hangga't nag-iingat ka, tulad ng ipinapakita sa halimbawa sa ibaba:

// a - sparse array var a = ; a = "a"; a = "b"; a = "c"; para sa (var key sa a) ( if (a.hasOwnProperty(key) && /^0$|^d*$/.test(key) && key<= 4294967294) { console.log(a); } }

Sa halimbawang ito, dalawang pagsusuri ang ginagawa sa bawat pag-ulit ng loop:

  1. na ang array ay may sariling ari-arian na tinatawag na susi (hindi minana mula sa prototype nito).
  2. ang key na iyon ay isang string na naglalaman ng decimal na representasyon ng isang integer na ang halaga ay mas mababa sa 4294967294 . Saan nagmula ang huling numero? Mula sa kahulugan ng isang array index sa ES5, na nagpapakita na ang pinakamataas na index na maaaring magkaroon ng isang elemento sa isang array ay: (2^32 - 2) = 4294967294 .

Siyempre, ang mga naturang pagsusuri ay kukuha ng hindi kinakailangang oras kapag isinasagawa ang loop. Ngunit sa kaso ng isang kalat-kalat na hanay, ang pamamaraang ito ay mas mahusay kaysa sa isang para sa loop, dahil sa kasong ito, ang mga elemento lamang na tahasang tinukoy sa array ang inuulit. Kaya, sa halimbawa sa itaas, 3 iteration lang ang isasagawa (para sa mga index 0, 10 at 10000) - versus 10001 sa for loop.

Upang hindi magsulat ng napakahirap na check code sa tuwing kailangan mong umulit sa isang array, maaari mo itong isulat bilang isang hiwalay na function:

Function arrayHasOwnIndex(array, key) ( return array.hasOwnProperty(key) && /^0$|^d*$/.test(key) && key<= 4294967294; }

Kung gayon ang katawan ng loop mula sa halimbawa ay makabuluhang bawasan:

Para sa (key in a) ( if (arrayHasOwnIndex(a, key)) ( console.log(a); ) )

Ang check code na tinalakay sa itaas ay pangkalahatan, na angkop para sa lahat ng kaso. Ngunit sa halip, maaari kang gumamit ng isang mas maikling bersyon, kahit na pormal na hindi ganap na tama, ngunit gayunpaman ay angkop para sa karamihan ng mga kaso:

Para sa (key in a) ( if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) ( console.log(a); ) )

4. Para sa...ng loop (implicit na paggamit ng iterator)

Ang ES6, na nasa status pa rin ng draft, ay dapat magpakilala ng mga iterator sa JavaScript.

Tagapag-ulit ay isang protocol na ipinatupad ng isang bagay na tumutukoy sa isang karaniwang paraan upang makakuha ng pagkakasunod-sunod ng mga halaga (finite o infinite).
Ang isang bagay ay may isang iterator kung ito ay tumutukoy sa isang susunod na() na pamamaraan, isang walang-argumentong function na nagbabalik ng isang bagay na may dalawang katangian:

  1. tapos na (boolean) - true kung naabot na ng iterator ang dulo ng iterable sequence. Kung hindi, ang halaga ay hindi totoo.
  2. halaga - tumutukoy sa halaga na ibinalik ng iterator. Maaaring hindi natukoy (nawawala) kung ang ginawang pag-aari ay totoo .

Maraming mga built-in na bagay, kasama. Ang mga tunay na array ay may mga iterator bilang default. Ang pinakasimpleng paraan para gumamit ng iterator sa mga totoong array ay ang paggamit ng bago para sa...ng construct.

Halimbawa ng paggamit para sa...ng:

Varval; var a = ["a", "b", "c"]; para sa (val ng a) ( console.log(val); )

Sa halimbawa sa itaas, ang for...of loop ay tahasang tumatawag sa Array object's iterator upang makuha ang bawat halaga ng array.

5. Tahasang paggamit ng iterator

Ang mga iterator ay maaari ding gamitin nang tahasan, gayunpaman, sa kasong ito ang code ay nagiging mas kumplikado kumpara sa para...ng loop. Mukhang ganito:

Var a = ["a", "b", "c"]; var entry; habang (!(entry = a.next()).tapos na) ( console.log(entry.value); )

II. Pag-ulit sa mga bagay na tulad ng array

Bilang karagdagan sa mga tunay na array, sa JavaScript mayroon din mga bagay na parang array . Ang pagkakapareho nila sa mga tunay na array ay mayroon silang haba na property at mga katangian na pinangalanan bilang mga numero na tumutugma sa mga elemento ng array. Kasama sa mga halimbawa ang DOM ng koleksyon ng NodeList at ang mga argumentong pseudo-array, na available sa loob ng anumang function/paraan.

1. Paggamit ng mga pamamaraan upang umulit sa mga totoong array

Sa pinakamababa, karamihan, kung hindi lahat, ang mga paraan ng pag-ulit sa mga totoong array ay maaaring gamitin upang umulit sa mga bagay na tulad ng array.

Ang para sa at para sa...in construct ay maaaring ilapat sa array-tulad ng mga bagay sa eksaktong parehong paraan tulad ng mga ito ay inilapat sa tunay na array.

forEach at iba pang Array.prototype na pamamaraan ay nalalapat din sa mga bagay na parang array. Upang gawin ito kailangan mong gamitin ang Function.call o Function.apply .

Halimbawa, kung gusto mong mag-apply para saEach sa childNodes property ng isang Node object, gagawin mo ito ng ganito:

Array.prototype.forEach.call(node.childNodes, function(child) ( // gumawa ng isang bagay sa child object));

Upang gawing mas madaling gamitin muli ang trick na ito, maaari kang magdeklara ng reference sa Array.prototype.forEach na pamamaraan sa isang hiwalay na variable at gamitin ito bilang isang shortcut:

// (Ipagpalagay na ang lahat ng code sa ibaba ay nasa parehong saklaw) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // do something with the child object));

Kung ang isang bagay na tulad ng array ay may isang iterator, maaari itong gamitin nang tahasan o hindi malinaw upang umulit sa object sa parehong paraan tulad ng para sa mga tunay na array.

2. I-convert sa isang tunay na array

Mayroon ding isa pa, napakasimpleng paraan upang umulit sa isang bagay na tulad ng array: i-convert ito sa isang tunay na array at gamitin ang alinman sa mga pamamaraan na tinalakay sa itaas para sa pag-ulit sa mga tunay na array. Para sa conversion, maaari mong gamitin ang generic na paraan ng Array.prototype.slice, na maaaring ilapat sa anumang bagay na parang array. Ginagawa ito nang napakasimple, tulad ng ipinapakita sa halimbawa sa ibaba:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);

Halimbawa, kung gusto mong i-convert ang isang NodeList na koleksyon sa isang aktwal na array, kakailanganin mo ng code na tulad nito:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);

3. Isang tala sa mga bagay sa runtime

Kung ilalapat mo ang mga pamamaraan ng Array.prototype sa mga runtime na bagay (gaya ng mga koleksyon ng DOM), dapat mong malaman na ang mga pamamaraang ito ay hindi garantisadong gagana nang tama sa lahat ng runtime na kapaligiran (kabilang ang mga browser). Depende ito sa pag-uugali ng isang partikular na bagay sa isang partikular na kapaligiran ng pagpapatupad, o mas tiyak, sa kung paano ipinapatupad ang abstract na operasyong HasProperty sa bagay na ito. Ang problema ay ang ES5 na pamantayan mismo ay nagbibigay-daan para sa posibilidad ng isang bagay na hindi kumikilos kaugnay ng operasyong ito (tingnan ang §8.6.2).

Samakatuwid, mahalagang subukan ang pagpapatakbo ng mga pamamaraan ng Array.prototype sa bawat runtime environment (browser) kung saan plano mong gamitin ang iyong application.