(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); Nokkur ráð til að flýta fyrir JavaScript-umsókninni þinni - The Codest
The Codest
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Iðnaðargreinar
    • Fjártæknifyrirtæki og bankastarfsemi
    • E-commerce
    • Adtech
    • Heilbrigðistækni
    • Framleiðsla
    • Flutningar
    • Bifreiða
    • Internet hlutanna
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
Aftur ör Farðu aftur
2019-10-08
Hugbúnaðarþróun

Nokkur ráð til að flýta fyrir JavaScript-umsókninni þinni

The Codest

Bartosz Slysz

Software Engineer

Með framþróun vafraaðgerða hafa vefumsóknir farið að flytja sífellt meiri rökfræði yfir á framhliðina, sem léttir á netþjóninum og dregur úr fjölda aðgerða sem hann þarf að framkvæma. Í grunn CRUD-aðgerðum felst hlutverk netþjónsins í heimildaveitingu, gildisskoðun, samskiptum við gagnagrunna og nauðsynlegri viðskiptarökfræði. Restin af gagnarökfræðinni, eins og kemur í ljós, má auðveldlega sinna með kóða sem sér um framsetningu forritsins á notendaviðmótinu.

Hér er tómt.

Í þessari grein mun ég reyna að sýna þér nokkur dæmi og mynstur sem munu hjálpa til við að halda okkar kóði hagkvæmt, snyrtilegt og fljótlegt.

Áður en við förum dýpra í sértækar dæmi – í þessari grein vil ég einblína eingöngu á að sýna dæmi sem, að mínu mati, geta haft áhrif á hraða forritsins á óvæntan hátt. Þetta þýðir þó ekki að notkun hraðari lausna sé besti kosturinn í öllum hugsanlegum tilvikum. Ráðin hér að neðan ætti frekar að skoða sem eitthvað sem vert er að skoða þegar forritið okkar gengur hægt, t.d. í vörum sem krefjast leikjagerðar eða flóknari línurita á striga, myndbandsvinnslu eða aðgerða sem þú vilt samstilla í rauntíma sem fyrst.

Fyrst og fremst – Array.prototype-aðferðir

Við byggjum stóran hluta af forritalógík forritsins á fylki – kortlagningu þeirra, röðun, síun, samanlagningu þátta og svo framvegis. Á einfaldan, gagnsæjan og náttúrulegan hátt notum við innbyggðar aðferðir þeirra sem einfaldlega gera okkur kleift okkur til að framkvæma ýmsar tegundir útreikninga, flokkana o.s.frv. Þau virka á svipaðan hátt í hverju tilviki – sem rök sendum við fall þar sem, í flestum tilfellum, gildi þáttarins, vísitalan og fylkið eru sett inn í röð við hverja endurtekningu. Tilgreinda fallið er keyrt fyrir hvern þátt í fylkinu og niðurstaðan er túlkuð mismunandi eftir aðferðinni. Ég mun ekki fjalla um Array.prototype-aðferðirnar þar sem ég vil einbeita mér að því hvers vegna það gengur hægt í mörgum tilfellum.

Aðferðir fylkja eru hægar vegna þess að þær framkvæma fall fyrir hvern þátt. Fall sem kallað er frá sjónarhóli vélarinnar þarf að undirbúa nýja köllun, útvega viðeigandi gildissvið og margar aðrar forsendur, sem gerir ferlið mun lengri en að endurtaka ákveðinn kóðabrot í tilteknu gildissviði. Og þetta er líklega næg bakgrunnsupplýsing til að gera okkur kleift að skilja eftirfarandi dæmi:

(() => {
const randomArray = [...Array(1E6).keys()].map(() => ({ value: Math.random() }));

console.time('Sum by reduce');
const reduceSum = randomArray
    .map(({ value }) => value)
    .reduce((a, b) => a + b);
console.timeEnd('Sum by reduce');

console.time('Sum by for loop');
let forSum = randomArray[0].value;
for (let index = 1; index < randomArray.length; index++) {
    forSum += randomArray[index].value;
}
console.timeEnd('Sum by for loop');

console.log(reduceSum === forSum);

})();

Ég veit að þetta próf er ekki eins áreiðanlegt og viðmiðin (við munum koma aftur að þeim síðar), en það kveikir viðvörunarljós. Í handahófskenndu tilfelli á tölvunni minni kemur í ljós að kóðinn með for-lykkjunni getur verið um 50 sinnum hraðari en að kortleggja og síðan fækka þáttum sem ná sama árangri! Þetta snýst um að vinna með einhvern undarlega hlut sem var búinn til eingöngu til að ná ákveðnu reikniframkvæmdasetmarki. Svo skulum við búa til eitthvað meira réttmætt til að vera hlutlægt um Array-aðferðirnar:

(() => {
const randomArray = [...Array(1E6).keys()].map(() => ({ value: Math.random() }));

console.time('Sum by reduce');
const reduceSum = randomArray
    .reduce((a, b) => ({ value: a.value + b.value })).value
console.timeEnd('Sum by reduce');

console.time('Sum by for loop');
let forSum = randomArray[0].value;
for (let index = 1; index < randomArray.length; index++) {
    forSum += randomArray[index].value;
}
console.timeEnd('Sum by for loop');

console.log(reduceSum === forSum);

})();

Ég veit að þetta próf er ekki eins áreiðanlegt og viðmiðin (við komum aftur að þeim síðar), en það kveikir viðvörunarljós. Í handahófskenndu tilfelli á tölvunni minni kemur í ljós að kóðinn með for-lykkjunni getur verið um 50 sinnum hraðari en mapping og síðan reducing á þáttum sem ná sama árangri! Þetta er vegna þess að til að fá summuna í þessu tiltekna tilfelli með reduce-aðferðinni þarf að framkvæma mapping á fylkinu til að búa til hreinar gildi sem við viljum samantekja. Svo skulum við búa til eitthvað meira viðeigandi til að vera hlutlæg um fylkisaðferðirnar:

(() => {
const randomArray = [...Array(1E6).keys()].map(() => ({ value: Math.random() }));

console.time('Sum by reduce');
const reduceSum = randomArray
    .reduce((a, b) => ({ value: a.value + b.value })).value
console.timeEnd('Sum by reduce');

console.time('Sum by for loop');
let forSum = randomArray[0].value;
for (let index = 1; index < randomArray.length; index++) {
    forSum += randomArray[index].value;
}
console.timeEnd('Sum by for loop');

console.log(reduceSum === forSum);

})();

Og eins og kom í ljós, minnkaði 50x hraðaaukningin okkar í 4x hraðaaukningu. Fyrirgefðu ef þú ert vonsvikinn! Til að halda hlutleysi til enda skulum við greina báða kóðana aftur. Í fyrsta lagi – saklausar útlitsmunir tvöfölduðu lækkunina í fræðilegri reikniflokkni okkar; í stað þess að kortleggja fyrst og svo leggja saman hreina þætti vinnum við enn með hluti og ákveðið svið til að að lokum draga fram þá upphæð sem okkur langar að fá. Vandamálið kemur upp þegar annar forritari skoðar kóðann – þá, borið saman við kóðana sem sýndir voru áður, tapar sá seinni abstraktíon sinni á einhverjum tímapunkti.

Þetta er vegna þess að frá annarri aðgerðinni vinnum við með undarlegu hlutinn, með reitinn sem okkur langar að skoða, og hinn venjulegi hlutinn úr endurteknu fylkinu. Ég veit ekki hvað þér finnst um þetta, en frá minni sjónarhóli er rökfræði for-lykkjunnar í öðru kóðadæminu mun skýrari og markvissari en þessi undarlega reduce-aðgerð. Og þrátt fyrir að það sé ekki lengur hið goðsagnakennda 50, er það samt fjórum sinnum hraðara hvað varðar útreikningstíma! Þar sem hver millisekúnda skiptir máli er valið í þessu tilfelli einfalt.

Mest óvænti dæmið

Annað sem ég vildi bera saman varðaði Math.max-aðferðina eða, nákvæmlega, að setja milljón þætti inn í hana og síðan draga út þá stærsta og minnsta. Ég undirbjó kóðann og aðferðir til að mæla tíma líka, kveikti á kóðanum og fékk mjög undarlega villu – staflstærð er yfirstigin. Hér er kóðinn:

(() => {
const randomValues = [...Array(1E6).keys()].map(() => Math.round(Math.random() * 1E6) - 5E5);

console.time('Math.max með ES6 spread-rekstraraðila');
const maxBySpread = Math.max(...randomValues);
console.timeEnd('Math.max með ES6 spread-rekstraraðila');

console.time('Math.max með for-lykli');
let maxByFor = randomValues[0];
for (let index = 1; index  maxByFor) {
 maxByFor = randomValues[index];
    }
}
console.timeEnd('Math.max with for loop');

console.log(maxByFor === maxBySpread);

})();
(() => {
const randomValues = [...Array(1E6).keys()].map(() => Math.round(Math.random() * 1E6) - 5E5);

console.time('Math.max með ES6 spread-rekstraraðila');
const maxBySpread = Math.max(...randomValues);
console.timeEnd('Math.max með ES6 spread-rekstraraðila');

console.time('Math.max með for-lykli');
let maxByFor = randomValues[0];
for (let index = 1; index  maxByFor) {
 maxByFor = randomValues[index];
    }
}
console.timeEnd('Math.max with for loop');

console.log(maxByFor === maxBySpread);

})();

Það kemur í ljós að innfæddar aðferðir nota endurköllun, sem í v8 er takmörkuð af köllunarsöfnum og fjöldi þeirra fer eftir umhverfinu. Þetta kom mér mjög á óvart, en það leiðir til einnar niðurstöðu: innfædda aðferðin er hraðari, svo framarlega sem fylkið okkar fer ekki yfir ákveðinn töfratölu þátta, sem í mínu tilfelli reyndist vera 125375. Fyrir þennan fjölda þátta var niðurstaðan 5 sinnum hraðari en lykkjan. Hins vegar, yfir þeim nefnda fjölda þátta, vinnur for-lykkjan hiklaust – ólíkt keppinautnum leyfir hún okkur að fá réttar niðurstöður.

Endurköllun

Hugtakið sem ég vil nefna í þessum málsgrein er sjálfköllun. Í fyrri dæminu sáum við það í Math.max-aðferðinni og í rökfellingu rökargilda, þar sem kom í ljós að ekki er hægt að fá niðurstöðu fyrir sjálfköllanir sem fara yfir ákveðinn fjölda vegna takmarkana á staflaloðdýpt.

Við munum nú sjá hvernig endurköllun lítur út í samhengi kóða sem er skrifaður í JS, og ekki með innbyggðum aðferðum. Kannski er klassískasta dæmið sem við getum sýnt hér, auðvitað, að finna n-ta hlið Fibonacci-raðarinnar. Svo skulum við skrifa þetta!

(() => {
const fiboIterative = (n) => {
let [a, b] = [0, 1];

 for (let i = 0; i  {
    if(n < 2) {
 return n;
    }

 return fiboRecursive(n - 2) + fiboRecursive(n - 1);
};

console.time('Fibonacci röð með for-lykkju');
const resultIterative = fiboIterative(30);
console.timeEnd('Fibonacci-raðir með for-hring');

console.time('Fibonacci-raðir með endurköllun');
const resultRecursive = fiboRecursive(30);
console.timeEnd('Fibonacci-raðir með endurköllun');

console.log(resultRecursive === resultIterative);

})();

Allt í lagi, í þessu tiltekna tilfelli að reikna 30. lið röðunnar á tölvunni minni fáum við niðurstöðuna á um það bil 200 sinnum styttri tíma með endurtekningalegum reikniritinu.

Það er þó eitt sem hægt er að laga í endurköllunaralgórítmanum – eins og kemur í ljós, virkar hann mun skilvirkari þegar við notum aðferð sem kallast halaendurhringing. Þetta þýðir að við sendum niðurstöðuna sem við fengum í fyrri endurtekningu sem rök fyrir dýpri köllum. Þetta gerir okkur kleift að draga úr fjölda kalla sem þarf og þar með hraða niðurstöðunni. Breytum kóðanum okkar í samræmi við þetta!

(() => {
const fiboIterative = (n) => {
let [a, b] = [0, 1];

    for (let i = 0; i  {
    if(n === 0) {
 return first;
    }

    return fiboTailRecursive(n - 1, second, first + second);
};

console.time('Fibonacci-raðir með for-lykkju');
const resultIterative = fiboIterative(30);
console.timeEnd('Fibonacci-raðir með for-lykkju');

console.time('Fibonacciröð með hala-endurköllun');
const resultRecursive = fiboTailRecursive(30);
console.timeEnd('Fibonacciröð með hala-endurköllun');

console.log(resultRecursive === resultIterative);

})();

Eitthvað sem ég ekki alveg bjóst við gerðist hér – niðurstaða halaendurköllunaralgórítmans gat skilað niðurstöðunni (reiknað 30. þátt röð) næstum tvisvar sinnum hraðar en endurtekningaralgórítminn í sumum tilvikum. Ég er ekki alveg viss um hvort þetta stafi af fínstillingu á halaendurtekningu hjá v8 eða skorti á fínstillingu á for-lykkjunni fyrir þennan tiltekna fjölda endurtekninga, en niðurstaðan er óyggjandi – halaendurtekningin vinnur.

Þetta er skrýtið því í grundvallaratriðum krefst for-lykkjan mun minni abstraktunar við lágstigs útreikninga og má segja að hún sé nær grunnreiknivélaraðgerðum. En niðurstöðurnar eru óyggjandi – snjallt hönnuð endurköllun reynist hraðari en endurtekningar.

Notaðu ósamhverfar kallyfirlýsingar eins oft og þú getur.

Mig langar að verja síðasta málsgreininni til stuttrar áminningar um aðferð til að framkvæma aðgerðir sem geta einnig haft veruleg áhrif á hraða forritsins okkar. Eins og þið ættuð að vita, JavaScript er einþráða forritunarmál sem heldur utan um allar aðgerðir með atburðarhringsvinnubragði. Allt snýst um hringrás sem keyrir endurtekið og hvert skref í þessari hringrás felur í sér sérhæfðar, tilgreindar aðgerðir.

Til að gera þessa lykkju hraða og láta alla hringi bíða minna eftir sinni töku, ættu allir þættir að vera eins snöggir og mögulegt er. Forðastu að keyra langvarandi aðgerðir á aðalþræði – ef eitthvað tekur of langan tíma, reyndu að færa þessar útreikningar í WebWorker eða skipta þeim upp í hluta sem keyra ósamstillt. Þetta getur hægjað á sumum aðgerðum en bætt allt JS-umhverfið, þar á meðal inntaks- og úttaks-aðgerðir, eins og að meðhöndla músarbíla hreyfingar eða biðjandi HTTP-beiðnir.

Yfirlit

Að lokum, eins og áður hefur komið fram, getur það reynst tilgangslaust í sumum tilvikum að elta millisekúndur sem hægt er að spara með vali á reiknirit. Á hinn bóginn getur það reynst banvænt fyrir forritið þitt að hunsa slíka þætti í forritum sem krefjast hnökralausrar vinnslu og hraðra niðurstaðna. Í sumum tilvikum, umfram hraða reikniritisins, þarf að spyrja eina viðbótar spurningu – er abstraktgerðin á réttum stigi? Mun forritarinn sem les kóðann geta skilið hann án vandræða?

Eini möguleikinn er að tryggja jafnvægi milli afkasta, einfaldleika innleiðingar og viðeigandi abstraktunar, og vera fullviss um að reikniritinu virki rétt bæði fyrir litlar og stórar magnir af gögn. Hvernig á að gera þetta er nokkuð einfalt – vertu snjall, íhugaðu mismunandi tilvik þegar þú hönnar reiknirit og skipuleggðu það til að virka eins skilvirkt og mögulegt er í meðalframkvæmdum. Einnig er ráðlegt að hanna prófanir – vertu viss um að reikniritinu skili viðeigandi upplýsingum fyrir mismunandi gögn, óháð því hvernig það virkar. Annast rétt viðmót – þannig að bæði inntak og úttak aðferða séu læsileg, skýr og endurspegli nákvæmlega hvað þau gera.

Ég nefndi áður að ég myndi koma aftur að áreiðanleika þess að mæla hraða reikniritanna í dæmunum hér að ofan. Að mæla þau með console.time er ekki mjög áreiðanlegt, en það endurspeglar best hefðbundna notkunartilvik. Allavega, hér eru niðurstöður samanburðarmælinganna – sumar þeirra líta aðeins öðruvísi út en ein framkvæmd vegna þess að samanburðarmælingar endurtaka einfaldlega tiltekna aðgerð á ákveðnum tíma og nýta v8-hagræðingu fyrir lykkjur.

  • https://jsben.ch/KhAqb – draga úr vs for-hringi
  • https://jsben.ch/F4kLY – hagræðing á reduce í for-hringi
  • https://jsben.ch/MCr6g – Math.max vs for hringrás
  • https://jsben.ch/A0CJB – endurkallandi Fibonacci vs. skrefbundinn Fibonacci
  • https://jsben.ch/NFLsl – halaendurkallandi fibo vs. endurtekningarbundinn fibo 

Og það er allt – njóttu hakksins þíns!

Lesa meira:

Hvernig má bæta Vue.js-forrit? Nokkur hagnýt ráð

Aðferðir til að auka afköst Rails

Hvernig á að skrifa góðan og vandaðan kóða?

Tengdar greinar

Myndskreyting af heilbrigðisforriti fyrir snjallsíma með hjartatákni og hækkandi heilsufarsgrafík, merkt með The Codest-merkinu, sem táknar stafræna heilsu og HealthTech-lausnir.
Hugbúnaðarþróun

Heilbrigðis-hugbúnaður: gerðir og notkunartilvik

Tólin sem heilbrigðisstofnanir treysta á í dag líta ekkert út eins og pappírsskjöl frá fyrri áratugum. Heilbrigðisforrit styðja nú heilbrigðiskerfi, sjúklingameðferð og nútímalega heilbrigðisþjónustu á klínískum og...

THECODEST
Yfirlitsmynd sem sýnir hnignandi súlurit með uppstrekktri ör og gullmynt sem táknar kostnaðarhagkvæmni eða sparnað. The Codest-merkið birtist í efra vinstra horni með slagorðinu "In Code We Trust" á ljósgráum bakgrunni.
Hugbúnaðarþróun

Hvernig á að stækka þróunarteymið án þess að fórna gæðum vörunnar

Ertu að stækka þróunarteymið þitt? Lærðu hvernig á að vaxa án þess að fórna gæðum vörunnar. Þessi leiðarvísir fjallar um merki um að kominn sé tími til að stækka, uppbyggingu teymisins, ráðningar, forystu og verkfæri—og hvernig teymið getur...

THECODEST
Hugbúnaðarþróun

Búðu til vefumsóknir sem þola framtíðina: innsýn frá sérfræðiteymi The Codest

Uppgötvaðu hvernig The Codest skarar fram úr við að búa til stigstækar, gagnvirkar vefumsóknir með nýjustu tækni, sem bjóða upp á hnökralausa notendaupplifun á öllum kerfum. Lærðu hvernig sérfræðiþekking okkar knýr fram stafræna umbreytingu og viðskipti...

THECODEST
Hugbúnaðarþróun

Topp 10 hugbúnaðarþróunarfyrirtæki í Lettlandi

Kynntu þér fremstu hugbúnaðarþróunarfyrirtæki Lettlands og nýstárlegar lausnir þeirra í nýjustu grein okkar. Uppgötvaðu hvernig þessir tækniforingjar geta hjálpað til við að efla fyrirtækið þitt.

thecodest
Lausnir fyrir fyrirtæki og vaxtarfyrirtæki

Grunnatriði í Java hugbúnaðarþróun: Leiðarvísir að árangursríkri útvistun

Kannaðu þessa ómissandi leiðbeiningu um árangursríka outsourcing Java hugbúnaðarþróun til að auka skilvirkni, afla aðgangs að sérfræðiþekkingu og tryggja árangur verkefna með The Codest.

thecodest

Gerðu þig áskrifanda að þekkingargrunni okkar og vertu upplýstur um sérfræðiþekkingu upplýsingatæknigeirans.

    Um okkur

    The Codest – Alþjóðlegt hugbúnaðarþróunarfyrirtæki með tæknimiðstöðvar í Póllandi.

    Bretland - Höfuðstöðvar

    • Skrifstofa 303B, 182-184 High Street North E6 2JA
      Lundúnir, England

    Pólland - staðbundin tæknimiðstöðvar

    • Fabryczna skrifstofugarður, Aleja
      Herbergi 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsjá, Pólland

    The Codest

    • Heim
    • Um okkur
    • Þjónusta
    • Case Studies
    • Vitið hvernig
    • Starfsferilmöguleikar
    • Orðabók

    Þjónusta

    • Það er ráðgjafi
    • Hugbúnaðarþróun
    • Bakendaþróun
    • Framhliðþróun
    • Staff Augmentation
    • Bakhliðaráþróunaraðilar
    • Skýjaverkfræðingar
    • Gagnaverkfræðingar
    • Annað
    • Gæðatryggingartæknimenn

    Auðlindir

    • Staðreyndir og goðsagnir um samstarf við utanaðkomandi hugbúnaðarþróunaraðila
    • Frá Bandaríkjunum til Evrópu: Af hverju ákveða bandarísk sprotafyrirtæki að flytja til Evrópu?
    • Samanburður á tæknifjarkerfisþróunarmiðstöðvum: Tech Offshore Europe (Pólland), ASEAN (Filippseyjar), Eurasia (Tyrkland)
    • Hvert eru helstu áskoranir CTO-a og CIO-a?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Höfundarréttur © 2026 af The Codest. Öll réttindi áskilin.

    is_ISIcelandic
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian lt_LTLithuanian is_ISIcelandic