Cum se configurează smartphone-uri și PC-uri. Portal de informare

JavaScript: Funcții. Programare functionala

Funcțiile JavaScript vă permit să organizați scripturi și să faceți mai ușor reutilizarea codului. În loc să creeze bucăți lungi de cod împrăștiate pe o pagină HTML, scripturile sunt organizate în grupuri logice.

Declararea și apelarea unei funcții JavaScript

Sintaxa funcției JavaScript este următoarea:

funcția ""nume"" (""argument1", ""argument2", ""argument3"" ...) ( ""operatori"" returnează ""valoare"" )

Numele determină ce vom numi funcția atunci când o numim. Argumentele specifică valorile care sunt transmise funcției pentru procesare. Secțiunea de instrucțiuni reprezintă corpul funcției care realizează prelucrarea. Declarația de returnare opțională vă permite să returnați o valoare.

Următorul exemplu arată o funcție definită în secțiunea unei pagini HTML și apelată în secțiune:

funcția sayHello() ( alert("Bună ziua!"); ) sayHello();

Transmiterea de argumente unei funcții

În exemplul de mai sus (funcția JavaScript tip text), nu sunt transmise niciun argument funcției. De obicei, o funcție este concepută pentru a efectua o acțiune cu mai multe argumente:

Un exemplu simplu de funcție a funcției JavaScript sayHello(zi, lună) ( alert("Bună ziua! Azi este " + zi + " " + luna); ) sayHello("24", "iulie"); sayHello ("1", "august"); sayHello ("24", "mai");

În acest exemplu, funcția JavaScript callback este apelată de mai multe ori, luând argumente care sunt apoi folosite pentru a crea un șir care este afișat în caseta de dialog. Pentru a face acest lucru fără funcție, ar trebui să repetați scriptul din secțiune de trei ori. Evident, utilizarea unei funcții este o abordare mai eficientă.

Returnarea unei valori dintr-o funcție

Instrucțiunea return este folosită pentru a returna o valoare dintr-o funcție și pentru a o utiliza în locul în care este apelată funcția. De exemplu, vom declara o funcție care adaugă două argumente și returnează rezultatul:

Un exemplu simplu de funcție JavaScript var result = addValues(10, 20) document.write("Result = " + result);

În exemplul de mai sus, trecem valorile 10 și 20 la funcția addValues. Funcția addValues ​​adaugă aceste două valori și returnează rezultatul. Instrucțiunea return atribuie rezultatul variabilei rezultat, care este apoi folosită pentru a crea un șir care este tipărit pe pagina HTML.

Un apel de funcție JavaScript poate fi efectuat în diferite locuri. De exemplu, nu este necesar să atribuiți rezultatul ca valoare a unei variabile. Îl puteți folosi direct ca argument când apelați document.write .

Este important de reținut că o funcție poate returna o singură valoare:

Un exemplu simplu de funcție JavaScript addValues(valoare1, valoare2) ( return value1 + value2; ) document.write("Result = " + addValues(10, 20));< 20"); }

Funcțiile JavaScript onclick pot fi utilizate și în instrucțiunile condiționate. De exemplu: Un exemplu simplu de funcție a funcției JavaScript addValues(value1, value2) ( return value1 + value2; ) if (addValues(10, 20) > 20) ( document.write("Result > 20"); ) else ( document.write ("Rezultat

Unde să plasați declarațiile de funcție

Există două locuri în care este recomandat să plasați declarațiile de returnare a funcției JavaScript: într-o secțiune a documentului HTML sau într-un fișier .js extern. A doua opțiune este considerată locația cea mai preferată, deoarece oferă cea mai mare flexibilitate.

Scopul creării de funcții este de a le face cât mai generale posibil pentru a maximiza reutilizarea.

Traducerea articolului „Înțelegerea funcțiilor JavaScript” a fost pregătită de echipa prietenoasă a proiectului.

Bine Rău

Orice programator știe bine ce funcții sunt și de ce sunt necesare. Cu toate acestea, funcțiile din Javascript au unele caracteristici speciale. Dacă ai programat în acest limbaj de mult timp, atunci probabil știi că există diferite . Dacă veniți dintr-o altă limbă, atunci când citiți unele articole cel mai probabil ați văzut asta, ciudată la prima vedere, declarație de funcție:

Var add = function(arg1, arg2) ( var sum = arg1 + arg2; return sum; ) var rezultat = add(5, 2); //rezultatul este acum 7

Adică, funcția, în primul rând, nu are un nume. În al doilea rând, este atribuit unei variabile, dar nu doar atribuit, dar corpul său merge chiar acolo. Personal, pentru mine, care am scris anterior în limbi precum VB, C++, un astfel de anunț a provocat nedumerire și neînțelegere a modului în care funcționează și de ce să-l scriu așa.

Sunt obișnuit cu declararea și apelul funcției „clasice”, astfel:

Și aici ajungem la caracteristicile funcțiilor din Javascript. Pentru ușurință de înțelegere, imaginați-vă că o funcție în JS este o valoare obișnuită, cum ar fi un număr sau un șir. Puteți scrie numărul 5 în variabila rezultat? Sau ceva mai complex, cum ar fi o matrice, și apoi afișați-l pe ecran? Puteți. Deci, dacă vă imaginați că o funcție este o valoare obișnuită, deși de structură foarte complexă, atunci prima metodă de declarare nu mai pare incredibilă.

Următorul fapt interesant este o continuare logică a primului. După ce punem date într-o variabilă, putem folosi numele acelei variabile pentru a trece datele într-o altă variabilă:

Var a = 5; var b = a; alerta(b); //va scoate 5

Lucrul obișnuit. Acum aruncați o privire la acest cod:

Var add = function(arg1, arg2) ( var sum = arg1 + arg2; returnare suma; ) var calcSum = adauga; alert(calcSum(5, 6)); //va tipări 11

Incepi sa ghicesti? Deoarece o funcție este ca o variabilă, o putem „multiplica” prin alocare obișnuită în alte variabile, transformându-le și în funcții. Acum calcSum poate adăuga și două numere. Totuși, codul

Var calcSum = add(1, 1); //calcSum este acum egal cu 2, aceasta nu este o funcție, ci o variabilă cu o alertă de număr(calcSum(5, 6)); //eroare

Nu va fi executat, deoarece în prima linie am atribuit nu funcția în sine, ci rezultatul execuției acesteia (parantezele indică faptul că funcția trebuie executată și nu atribuită).

Dacă trebuie să apelați o funcție pe ea însăși, acest lucru se face după cum urmează:

Var calcFact = function fact(val) ( if (val == 1) ? val: val * fact(val - 1); //calcularea factorialului folosind recursiunea ) alert(calcFact(4)); //va tipări 24

Aici, atunci când atribuim o funcție unei variabile, am numit-o fapt. Cu toate acestea, acest nume va fi disponibil numai în cadrul funcției în sine și nicăieri altundeva. Motivele pentru aceasta se află în principiul modului în care interpretul funcționează și depășesc domeniul de aplicare al lecției.

S-ar putea să vă întrebați: „Hmm, oportunitate interesantă, dar care este avantajul acestei metode?”. Nu mă voi angaja să spun că există situații în care este imposibil să faci fără o astfel de abordare, dar pot da un exemplu în care se reduce cantitatea de cod. Să presupunem că trebuie să salutați o persoană în funcție de momentul zilei:

Var data = data noua(); var salut = (date.getHours()< 12) ? function() {alert("Доброе утро!")} : (date.getHours() < 18) ? function() {alert("Добрый день!")} : function() {alert("Добрый вечер!")}; hello();

După cum puteți vedea, funcțiile sunt extrem de simple, cu o singură comandă de alertă.

Dacă am decide să mergem pe „traseul clasic”, ar trebui să scriem trei funcții separate și apoi să le apelăm în condiția de verificare a timpului:

Funcția goodMorning() ( alert("Bună dimineața!"); ) function goodAfternoon() ( alert("Bună ziua!"); ) function goodEvning() ( alert("Bună seara!"); ) var data = data nouă (); (date.getHours()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

Codul a crescut semnificativ din punct de vedere vizual, chiar și ținând cont că am folosit forma scurtă a declarației condiționate. Dacă presupunem că fișierul conține funcții cu adevărat importante care efectuează calcule, atunci împrăștierea listei cu astfel de mini-funcții care nu poartă o logică importantă și care sunt, cel mai probabil, folosite o singură dată, nu este o idee bună. În plus, suntem forțați să dăm fiecărei funcție un nume unic și să îl indicăm atunci când apelăm. Prin urmare, dacă trebuie să schimbați numele unuia dintre ele, va trebui să îl schimbați în două locuri, ceea ce crește probabilitatea unei erori.

În al doilea rând, dacă folosim metoda „clasică”, pierdem capacitatea de a atribui o funcție unei variabile. Adică scrie

Funcția add(a, b) ( return a + b; ) var calcSum = add; calcSum(5, 5);

Nu se mai poate. Prin urmare, în exemplul nostru, dacă mai trebuie să salutăm oaspetele de mai multe ori, va trebui să duplicăm acest fragment de fiecare dată:

(date.getHours()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

Și în primul caz va fi suficient să scrieți doar salut(); iar rezultatul va fi același.

Ți-am spus despre o caracteristică interesantă a funcțiilor JS și am dat exemple. Astfel, ați văzut că modalitățile de a apela funcții în Javascript nu se limitează la un singur tip. Chiar dacă nu puteți găsi imediat utilizarea acestor capacități în proiectele dvs., cel puțin veți ști că astfel de oportunități există. Și când apare o oportunitate foarte bună, puteți reduce cantitatea de cod și puteți evita confuziile și erorile inutile!

Ideile de a genera dinamic conținut pe o resursă web au devenit norma. Crearea paginilor statice și a șablonului site-ului și-au îndeplinit în sfârșit misiunea.

Cu toate acestea, o resursă web modernă nu trebuie neapărat reprezentată de un set de pagini generate de server și actualizate de browser (JS+AJAX).

Când sosește un vizitator, o resursă web poate consta din câteva antete pentru protocol, ceva text în „cap”, câteva linii de cod în „corp” și atât. Restul " va veni cu o idee” în timpul experienței vizitatorului - acesta este un site ideal sau care aspiră să fie astfel.

Locul descrierii și esența funcțiilor

JavaScript este o experiență acumulată de-a lungul mai multor decenii. Are o istorie semnificativă de dezvoltare și o echipă modernă și calificată de creatori și dezvoltatori. Limbajul este bine gândit, de încredere, frumos și oferă dezvoltatorilor o oportunitate reală de a scrie cod decent și de a se îmbunătăți.

Conceptul de algoritm în afara unei funcții este absent aici în principiu. Desigur, dezvoltatorul poate introduce un script oriunde pe pagină, plasează codul în el și va fi executat. Dar care este scopul codului care se execută o singură dată: când pagina este încărcată (reîncărcată)? Cu excepția cazului în care este posibil să setați valorile inițiale ale unor variabile neimportante.

Un script este un loc pentru descrierea variabilelor și funcțiilor necesare, mai degrabă decât o bucată bună de cod scrisă de dragul său. Setul de funcții este esențial și semnificativ, poate legătura lor reciprocă directă, dar de cele mai multe ori totul este diferit. Locul în care este descrisă o funcție și locul în care este aplicată nu sunt deloc același lucru.

Nu este deloc necesar ca o funcție să apeleze direct o altă funcție, aceasta poate face indirect prin generarea de cod dinamic. Vizitatorul ia o decizie în cadrul acestui cod și este declanșat un sistem complet diferit de funcții.

Dinamica funcțională

Dinamica funcțională nu sunt doar și nu atât handlerii alocați elementelor de pagină, sunt funcțiile care formează elementele paginii, iar handlerii direcți se pot schimba și ei.

Acțiunea de pe pagină se desfășoară în funcție de elementele acesteia și de comportamentul vizitatorului pe ea. Mișcările mouse-ului, butoanele de la tastatură, clicurile, evenimentele de elemente și alte circumstanțe duc la lansarea funcțiilor necesare.

Inițial nu există o secvență și nu există paralelism. Există un răspuns adecvat al resursei web la evenimente. Cât de repede JavaScript va îndeplini o anumită funcție depinde de mulți factori tehnici (calculator, linii de comunicare) și semantici (logica algoritmului, domeniu, sensul sarcinii).

De fapt, se poate spune că ceva a funcționat în paralel și ceva se va împlini după ceva, dar acest lucru nu are o semnificație specială. Este important ca funcțiile JavaScript să ofere capacitatea de a crea un răspuns adecvat la acțiunile vizitatorilor.

Aceasta este o nouă gândire în dezvoltare: procesarea informațiilor distribuite în măruntaiele unui singur browser!

Sintaxa variabilelor și funcțiilor

Variabilele JavaScript sunt plasate atât în ​​eticheta „script”, cât și în corpul funcției. Funcțiile sunt definite în același mod. Nu are rost să scrieți o altă funcție în interiorul unei funcții, dar acest lucru poate fi necesar din motive diverse și bine întemeiate.

O descriere a funcției începe, în general, cu cuvântul cheie „funcție”, urmat de numele acestuia, o listă de argumente între paranteze separate prin virgule și corpul funcției între acolade.

Acest exemplu descrie două funcții care asigură schimbul AJAX între pagină și server. Variabila scXHR este descrisă mai sus, prin urmare este disponibilă atât în ​​InitXML, cât și în WaitReplySC.

Numele funcției și parametrul „funcție”.

Aici a fost introdusă o opțiune asincronă, în care funcția JavaScript din funcție este apelată după ce serverul răspunde. În același timp, după ce a primit un răspuns de la server, WaitReplySC accesează etichetele paginii, le completează cu informațiile primite și apelează alte funcții care ar putea iniția următoarea solicitare către server.

De asemenea, este important să rețineți că WaitReplySC este o funcție. Dar în linie scXHR.onreadystatechange = WaitReplySC este trecut ca parametru. Aceasta este o regulă generală pentru trecerea funcțiilor altor funcții ca parametri. Specificați paranteze și transmiteți parametrii săi în ele - funcția va fi executată imediat. Mi-a dat doar numele lui, dar ce. Apelul de funcție va fi efectuat de cel care i-a primit numele.

Funcționalitatea implementată prin AJAX vă permite să efectuați un apel către o funcție JavaScript prin datele primite de la server. De fapt, atunci când trimiteți o solicitare către server, este posibil ca o anumită funcție să nu „știe” deloc ce funcție accesează și cu ce informații.

Ieșirea funcției și rezultatul acesteia

În corpul funcției, puteți scrie orice operatori ai limbii, care, de fapt, este destinat acestui scop. Variabilele definite în interiorul și în afara unei funcții sunt disponibile în cadrul unei funcții, dar nu și cele definite în alte funcții.

Dacă doriți ca o funcție să returneze un rezultat, puteți utiliza instrucțiunea JavaScript return: return. În corpul funcției poate exista un număr suficient de instrucțiuni return. Nu este deloc necesar ca toate să returneze același tip de rezultat.

De obicei, dezvoltatorii respectă foarte mult această funcție și, în funcție de situație, decid să părăsească funcția cât mai curând posibil.

Nu este deloc necesar să parcurgeți întregul algoritm al funcției când puteți ieși mai devreme.

Argumente ale funcției

Argumentele unei funcții sunt transmise ca o listă separată prin virgulă, incluse în paranteze și situate imediat după numele acesteia. Numele de variabile sunt folosite ca argumente, dar și valorile pot fi transmise direct. Pentru a transmite o funcție unei funcții în JavaScript, trebuie doar să specificați numele acesteia fără paranteze.

În interiorul funcției, este disponibilă variabila arguments, care are proprietatea length. Puteți accesa orice argument de funcție prin argumente , argumente , ... până la ultimele argumente .

Modificarea unui argument de funcție este valabilă în interiorul funcției, dar nu în afara acesteia. Pentru a schimba ceva în afara funcției, trebuie să utilizați operatorul de returnare JavaScript, prin care treceți valoarea necesară în exterior.

După finalizarea funcției, tot ceea ce este asociat cu execuția acesteia va fi distrus. În timpul execuției, o funcție poate modifica variabile externe, cu excepția celor descrise în alte funcții, inclusiv în cele interne.

arguments are o proprietate apelată, care are scopul de a apela o funcție care este executată la un moment dat. Dacă vă autodenominați, versiunea JavaScript a unei funcții din cadrul unei funcții vă permite să implementați recursiunea.

Utilizarea Funcțiilor

Principala preocupare a funcțiilor este de a servi evenimentele din browser. Pentru a face acest lucru, în aproape fiecare etichetă este posibil să specificați numele evenimentului și funcția care îl procesează. Pot fi specificate mai multe evenimente, dar este specificată o singură funcție pentru fiecare eveniment.

O singură funcție poate servi mai multe elemente de pagină și mai multe evenimente. Folosind parametrul „acest”, puteți transmite informații către funcția de unde au fost apelate.

O utilizare clasică a funcțiilor JS este gestionarea evenimentelor pe elemente. În acest exemplu, funcția scfWecomeGo() sau scfWelcomeCancel() va fi apelată în formularul de autentificare/deconectare a vizitatorului și scfMenuItemClick(this) la selectarea modului de operare.

În acest din urmă caz, este trecut parametrul „acest”, ceea ce vă permite să aflați în mod miraculos de la ce div a venit apelul. În general, JavaScript este atât de bine implantat în DOM și vă permite să navigați prin elementele sale atât de convenabil și să colectați informațiile necesare, încât dinamica paginii poate fi pur și simplu imprevizibilă.

O funcție nu trebuie să returneze un șir de caractere, un număr sau o altă funcție. Poate returna un element HTML cu drepturi depline, care va conține numărul necesar de elemente, cu propriii handlere de evenimente.

Prin plasarea unui astfel de element pe pagină, dezvoltatorul creează o nouă funcționalitate, care este bună în ceea ce privește rezolvarea problemei și satisfacerea intereselor vizitatorilor, dar destul de dificilă în ceea ce privește implementarea.

Când începeți o astfel de dezvoltare cu funcții complete, este ușor să vă confundați în propriul cod, în apelurile de funcții, în momentele în care se formează cutare sau cutare conținut al unei părți a paginii. Înainte de a lua această direcție de dezvoltare, nu strica să cântăriți totul cu atenție.

Despre gândirea distribuită

Dezvoltatorul trebuie să gândească la nivelul tuturor elementelor paginii, la nivelul tuturor evenimentelor și să aibă o idee clară despre cum se întâmplă de fapt totul. Este greu, dar munca merită.

În JavaScript, execuția unei funcții poate fi amânată până când apare un eveniment și pot exista multe astfel de funcții, iar evenimentele tind să se propage și să cadă în „sfera de vizibilitate” a diverșilor handleri.

În acest exemplu, a fost apelată undeva mai devreme o funcție care a inițiat crearea unui element de meniu de navigare a fișierelor. Se presupune o organizare a paginii, adică există doar șapte fișiere în fereastră care pot fi șterse și procesate. Puteți naviga fie făcând clic pe o linie a fișierului, folosind săgețile de pe tastatură, fie în blocuri de șapte linii.

Fiecare caz are propriile sale funcții. Cu alte cuvinte, într-un exemplu atât de simplu este necesar să scrieți câteva zeci de funcții care vor răspunde la diverse evenimente, iar unele dintre aceste funcții vor procesa diverse opțiuni și situații care nu au deloc legătură cu evenimente.

De exemplu, când ștergeți un rând, cei de jos ar trebui să se miște în sus. Pentru a face acest lucru, va trebui fie să faceți o nouă selecție, care este trivială și consumatoare de resurse, fie să recalculați liniile, să utilizați funcții matrice în javascript și să atingeți obiectivul în mod elegant.

Argumente și rezultate ale funcției

JavaScript vă permite să vă aduceți codul într-o stare „complet funcțională”. Este normal ca argumentul unei funcții să fie o funcție. O opțiune este permisă atunci când funcția returnează o funcție. JavaScript este complet relaxat în acest sens.

Acesta este un mecanism bun, dar destul de complex în ceea ce privește implementarea. Din punct de vedere tehnic, totul este permis numai un dezvoltator calificat poate oferi semantic logica pentru transferul „funcționalității”.

Când în JavaScript există o funcție într-o funcție, totul merge bine, dar când o funcție generează o funcție, iar aceea generează alta, atunci este destul de dificil să urmezi logica. În esență, nu este vorba de aplicarea calificării, ci de obținerea unui rezultat sigur și corect.

Preocuparea dezvoltatorului este clară și simplă. Există o sarcină, aveți nevoie de o soluție, nu de o eroare de genul „Eroare JavaScript operația este nesigură”, un ecran gol sau oprirea întregului motor de browser.

Dacă argumentul este o funcție, atunci dezvoltatorul transmite o variabilă cu proprietăți speciale, adică nu este un număr, nu este un șir, nu este un obiect. Dar utilizarea unui astfel de argument poate duce la modificarea variabilelor externe și la executarea rezultatului funcției. În funcție de ceea ce se transmite, se vor face modificări adecvate.

Executarea codului generat

Puteți implementa execuția codului generat în timpul funcționării altui cod folosind „eval”. Aceasta nu este considerată o soluție grozavă, dar adesea nu puteți complica codul cu funcții inutile, ci vă limitați la formarea banală a unei linii de cod JavaScript și pur și simplu îl executați.

În acest exemplu, este generată o linie pentru a insera unele informații în div-ul curent. Numărul div și conținutul informațiilor sunt diferite pentru diferite poziții, astfel încât o astfel de soluție în această situație nu este garantată să ofere situația „eroare javascript operația este nesigură”, dar va da în mod fiabil efectul dorit.

O nuanță a paradigmei JavaScript „funcție într-o funcție”.

Dacă există o oportunitate de a face fără bibelouri, este mai bine să profitați de ea. Toate opțiunile enumerate sunt bune. Desigur, în multe cazuri aceasta este singura soluție.

Un exemplu clasic de recursivitate: calculul factorial. Este destul de dificil să scrii un algoritm care intră într-o buclă, dar este foarte ușor să treci dincolo de limitele valorii. Factorialul crește prea repede.

Cu toate acestea, atât recursiunea cât și o funcție care apelează o altă funcție care poate face un apel invers valid sunt normale.

De exemplu, o masă obișnuită. În tabel pot exista și alte tabele. Imbricarea nu poate fi limitată. Scrierea propriului set de funcții pentru fiecare tabel este prea mult un lux.

Există multe astfel de exemple care pot fi date și toate acestea vor fi sarcini reale și presante, deloc din domeniul programării. De aceea, problema constă tocmai în faptul că este imposibil să faci fără bibelouri sistemul de funcții creat, sau mai degrabă depanarea și funcționarea ulterioară fiabilă, devine preocuparea nu a JavaScript-ului, ci a dezvoltatorului.

24 mai 2011 la 01:13 Cinci moduri de a apela o funcție
  • JavaScript
  • Traducere

Întâlnesc adesea cod JavaScript în care erorile sunt cauzate de o înțelegere greșită a modului în care funcționează funcțiile în JavaScript (apropo, o mare parte din acest cod a fost scris de mine). JavaScript este un limbaj cu mai multe paradigme și are mecanisme de programare funcționale. Este timpul să explorezi aceste posibilități. În acest articol, vă voi spune cinci moduri de a apela funcții în JavaScript.

În primele etape ale învățării JavaScript, începătorii cred de obicei că funcțiile din acesta funcționează în același mod ca și în, de exemplu, C#. Dar mecanismele de apelare a funcțiilor din JavaScript au o serie de diferențe importante, iar ignorarea lor poate duce la erori care nu vor fi ușor de găsit.

Să scriem o funcție simplă care returnează o matrice de trei elemente - această valoare curentă și cele două argumente transmise funcției.
funcția makeArray(arg1, arg2)( return [acesta, arg1, arg2];)

Cel mai comun mod: apel global Începătorii declară adesea funcții așa cum se arată în exemplul de mai sus. Apelarea acestei funcții este ușoară:
makeArray ("unu", "două"); // => [ fereastră, „unu”, „două” ]
Așteaptă. De unde vine obiectul fereastră? De ce este egal cu fereastra?

În JavaScript, indiferent dacă scriptul este executat în browser sau într-un alt mediu, acesta este întotdeauna definit obiect global. Orice cod din scriptul nostru care nu este „legat” la nimic (adică în afara declarației obiectului) este de fapt în contextul obiectului global. În cazul nostru, makeArray nu este doar o funcție „mergând” pe cont propriu. De fapt, makeArray este o metodă a ferestrei obiectului global (în cazul executării codului în browser). Este ușor de dovedit:
alert(tipul ferestrei.methodThatDoesntExist); // => alertă nedefinită (tip de fereastră.makeArray); // => funcția
Adică, apelarea makeArray(„unu”, „două”); este echivalent cu apelarea window.makeArray(„unu”, „două”); .

Mă întristează că acesta este cel mai comun mod de a apela funcții, deoarece implică prezența unei funcții globale. Și știm cu toții că funcțiile și variabilele globale nu sunt cea mai bună formă în programare. Acest lucru este valabil mai ales pentru JavaScript. Evitați definițiile globale și nu veți regreta.

Regula de apelare a funcției #1: Dacă o funcție este apelată direct, fără a specifica un obiect (de exemplu, myFunction()), valoarea acestuia va fi obiectul global (fereastra dacă codul este executat în browser).

Apelarea unei metode Să creăm un obiect simplu și să facem makeArray metoda sa. Să declarăm obiectul folosind notația literală și apoi să apelăm metoda noastră:
// creează un obiect var arrayMaker = ( someProperty: „o valoare”, make: makeArray ); // apelează metoda make() arrayMaker.make("unu", "două"); // => [ arrayMaker, „unu”, „două” ] // sintaxă alternativă, folosiți paranteze drepte arrayMaker[„make”](„unu”, „două”); // => [ arrayMaker, „unu”, „două” ]
Vedeți diferența? Valoarea acestui lucru în acest caz este obiectul însuși. De ce nu window , ca în cazul precedent, deoarece declarația funcției nu s-a schimbat? Secretul este modul în care funcțiile sunt transmise în JavaScript. Funcția este un tip JavaScript standard care este de fapt un obiect și, ca orice alt obiect, funcțiile pot fi transmise și copiate. În acest caz, în esență, am copiat întreaga funcție, inclusiv lista de argumente și corpul, și am atribuit obiectul rezultat proprietății make a obiectului arrayMaker. Aceasta este echivalentă cu o declarație ca aceasta:
var arrayMaker = ( someProperty: „O anumită valoare”; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
Regula de apelare a funcției #2: Într-o funcție numită folosind sintaxa apelului de metodă, cum ar fi obj.myFunction() sau obj["myFunction"]() , aceasta va avea valoarea obj .

Înțelegerea greșită a acestui principiu în general simplu duce adesea la erori la procesarea evenimentelor:
function buttonClicked())( var text = (aceasta === fereastra) ? "window": this.id; alert(text); ) var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = buttonClicked; button2.onclick = function())( buttonClicked(); );
Făcând clic pe primul buton, se va afișa un mesaj "btn1" deoarece în acest caz apelăm o funcție ca metodă, iar aceasta în interiorul funcției va obține valoarea obiectului căruia îi aparține această metodă. Făcând clic pe al doilea buton, veți obține "fereastră" pentru că în acest caz apelăm direct buttonClicked (adică nu ca obj.buttonClicked()). Același lucru se întâmplă atunci când atribuim un handler de evenimente etichetei elementului, ca în cazul celui de-al treilea buton. Făcând clic pe al treilea buton, se va afișa același mesaj ca al doilea.

Când utilizați biblioteci precum jQuery, nu trebuie să vă gândiți la asta. jQuery va avea grijă să rescrie valoarea this în handlerul de evenimente, astfel încât valoarea this să fie elementul care a generat evenimentul:
// folosește jQuery $("#btn1").click(function() ( alert(this.id); // jQuery se va asigura că "acest" este un buton ));
Cum reușește jQuery să schimbe valoarea acestuia? Citiți mai jos.

Încă două moduri: apply() și call() Este logic că cu cât folosiți mai des funcții, cu atât mai des trebuie să le treceți și să le apelați în contexte diferite. Adesea este nevoie de a trece peste valoarea acestuia. Dacă vă amintiți, funcțiile din JavaScript sunt obiecte. În practică, aceasta înseamnă că funcțiile au metode predefinite. apply() și call() sunt două dintre ele. Acestea vă permit să suprascrieți această valoare:
var masina = (an: 2008, model: "Dodge Bailout"); makeArray.apply(mașină, [ „unu”, „două” ]); // => [ mașină, „unu”, „două” ] makeArray.call(mașină, „unu”, „două”); // => [ mașină, „unu”, „două” ]
Aceste două metode sunt foarte asemănătoare. Primul parametru îl înlocuiește. Diferențele dintre ele sunt în argumentele ulterioare: Function.apply() acceptă o matrice de valori care vor fi transmise funcției, în timp ce Function.call() acceptă argumentele separat. În practică, după părerea mea, este mai convenabil să folosiți apply() .

Regula de apelare a funcției #3: Dacă doriți să suprascrieți valoarea acesteia fără a copia funcția într-un alt obiect, puteți utiliza myFunction.apply(obj) sau myFunction.call(obj) .

Constructori Nu mă voi opri în detaliu asupra declararii unor tipuri personalizate în JavaScript, dar cred că este necesar să vă reamintesc că nu există clase în JavaScript și orice tip definit de utilizator are nevoie de un constructor. În plus, este mai bine să declarați metode de tip personalizat folosind prototype , care este o proprietate a funcției de constructor. Să ne creăm propriul tip:
// declară funcția constructor ArrayMaker(arg1, arg2) ( this.someProperty = "nu contează"; this.theArray = [ this, arg1, arg2 ]; ) // declar metode ArrayMaker.prototype = ( someMethod: function () ( alert( "Apelat de someMethod"); getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker ("unu", "două"); var other = new ArrayMaker ("primul", "al doilea"); am.getArray(); // => [ am, „unu”, „doi” ]
Lucrul important în acest exemplu este prezența noului operator înainte de apelul funcției. Dacă nu ar fi, ar fi un apel global, iar proprietățile create în constructor ar aparține obiectului global. Nu avem nevoie de asta. În plus, constructorii de obicei nu returnează valori în mod explicit. Fără noul operator, constructorul ar returna nedefinit, cu el returnează acest lucru. Se consideră un stil bun de a numi constructorii cu majuscule; Acest lucru vă va aminti de necesitatea noului operator.

În caz contrar, codul din interiorul constructorului va fi probabil similar cu codul pe care l-ați scrie într-o altă limbă. Valoarea acestuia în acest caz este noul obiect pe care îl creați.

Regula de apelare a funcției #4: Când apelați o funcție cu noul operator, valoarea acestuia va fi un obiect nou creat de runtime JavaScript. Dacă această funcție nu returnează niciun obiect în mod explicit, acesta va fi returnat implicit.

Concluzie Sperăm că înțelegerea diferenței dintre diferitele moduri de a apela funcții vă va ajuta să vă îmbunătățiți codul JavaScript. Uneori, erorile legate de această valoare sunt greu de detectat, așa că este logic să le preveniți în avans.
  • Traducere

Întâlnesc adesea cod JavaScript în care erorile sunt cauzate de o înțelegere greșită a modului în care funcționează funcțiile în JavaScript (apropo, o mare parte din acest cod a fost scris de mine). JavaScript este un limbaj cu mai multe paradigme și are mecanisme de programare funcționale. Este timpul să explorezi aceste posibilități. În acest articol, vă voi spune cinci moduri de a apela funcții în JavaScript.

În primele etape ale învățării JavaScript, începătorii cred de obicei că funcțiile din acesta funcționează în același mod ca și în, de exemplu, C#. Dar mecanismele de apelare a funcțiilor din JavaScript au o serie de diferențe importante, iar ignorarea lor poate duce la erori care nu vor fi ușor de găsit.

Să scriem o funcție simplă care returnează o matrice de trei elemente - această valoare curentă și cele două argumente transmise funcției.
funcția makeArray(arg1, arg2)( return [acesta, arg1, arg2];)

Cel mai comun mod: apel global Începătorii declară adesea funcții așa cum se arată în exemplul de mai sus. Apelarea acestei funcții este ușoară:
makeArray ("unu", "două"); // => [ fereastră, „unu”, „două” ]
Așteaptă. De unde vine obiectul fereastră? De ce este egal cu fereastra?

În JavaScript, indiferent dacă scriptul este executat în browser sau într-un alt mediu, acesta este întotdeauna definit obiect global. Orice cod din scriptul nostru care nu este „legat” la nimic (adică în afara declarației obiectului) este de fapt în contextul obiectului global. În cazul nostru, makeArray nu este doar o funcție „mergând” pe cont propriu. De fapt, makeArray este o metodă a ferestrei obiectului global (în cazul executării codului în browser). Este ușor de dovedit:
alert(tipul ferestrei.methodThatDoesntExist); // => alertă nedefinită (tip de fereastră.makeArray); // => funcția
Adică, apelarea makeArray(„unu”, „două”); este echivalent cu apelarea window.makeArray(„unu”, „două”); .

Mă întristează că acesta este cel mai comun mod de a apela funcții, deoarece implică prezența unei funcții globale. Și știm cu toții că funcțiile și variabilele globale nu sunt cea mai bună formă în programare. Acest lucru este valabil mai ales pentru JavaScript. Evitați definițiile globale și nu veți regreta.

Regula de apelare a funcției #1: Dacă o funcție este apelată direct, fără a specifica un obiect (de exemplu, myFunction()), valoarea acestuia va fi obiectul global (fereastra dacă codul este executat în browser).

Apelarea unei metode Să creăm un obiect simplu și să facem makeArray metoda sa. Să declarăm obiectul folosind notația literală și apoi să apelăm metoda noastră:
// creează un obiect var arrayMaker = ( someProperty: „o valoare”, make: makeArray ); // apelează metoda make() arrayMaker.make("unu", "două"); // => [ arrayMaker, „unu”, „două” ] // sintaxă alternativă, folosiți paranteze drepte arrayMaker[„make”](„unu”, „două”); // => [ arrayMaker, „unu”, „două” ]
Vedeți diferența? Valoarea acestui lucru în acest caz este obiectul însuși. De ce nu window , ca în cazul precedent, deoarece declarația funcției nu s-a schimbat? Secretul este modul în care funcțiile sunt transmise în JavaScript. Funcția este un tip JavaScript standard care este de fapt un obiect și, ca orice alt obiect, funcțiile pot fi transmise și copiate. În acest caz, în esență, am copiat întreaga funcție, inclusiv lista de argumente și corpul, și am atribuit obiectul rezultat proprietății make a obiectului arrayMaker. Aceasta este echivalentă cu o declarație ca aceasta:
var arrayMaker = ( someProperty: „O anumită valoare”; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
Regula de apelare a funcției #2: Într-o funcție numită folosind sintaxa apelului de metodă, cum ar fi obj.myFunction() sau obj["myFunction"]() , aceasta va avea valoarea obj .

Înțelegerea greșită a acestui principiu în general simplu duce adesea la erori la procesarea evenimentelor:
function buttonClicked())( var text = (aceasta === fereastra) ? "window": this.id; alert(text); ) var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = buttonClicked; button2.onclick = function())( buttonClicked(); );
Făcând clic pe primul buton, se va afișa un mesaj "btn1" deoarece în acest caz apelăm o funcție ca metodă, iar aceasta în interiorul funcției va obține valoarea obiectului căruia îi aparține această metodă. Făcând clic pe al doilea buton, veți obține "fereastră" pentru că în acest caz apelăm direct buttonClicked (adică nu ca obj.buttonClicked()). Același lucru se întâmplă atunci când atribuim un handler de evenimente etichetei elementului, ca în cazul celui de-al treilea buton. Făcând clic pe al treilea buton, se va afișa același mesaj ca al doilea.

Când utilizați biblioteci precum jQuery, nu trebuie să vă gândiți la asta. jQuery va avea grijă să rescrie valoarea this în handlerul de evenimente, astfel încât valoarea this să fie elementul care a generat evenimentul:
// folosește jQuery $("#btn1").click(function() ( alert(this.id); // jQuery se va asigura că "acest" este un buton ));
Cum reușește jQuery să schimbe valoarea acestuia? Citiți mai jos.

Încă două moduri: apply() și call() Este logic că cu cât folosiți mai des funcții, cu atât mai des trebuie să le treceți și să le apelați în contexte diferite. Adesea este nevoie de a trece peste valoarea acestuia. Dacă vă amintiți, funcțiile din JavaScript sunt obiecte. În practică, aceasta înseamnă că funcțiile au metode predefinite. apply() și call() sunt două dintre ele. Acestea vă permit să suprascrieți această valoare:
var masina = (an: 2008, model: "Dodge Bailout"); makeArray.apply(mașină, [ „unu”, „două” ]); // => [ mașină, „unu”, „două” ] makeArray.call(mașină, „unu”, „două”); // => [ mașină, „unu”, „două” ]
Aceste două metode sunt foarte asemănătoare. Primul parametru îl înlocuiește. Diferențele dintre ele sunt în argumentele ulterioare: Function.apply() acceptă o matrice de valori care vor fi transmise funcției, în timp ce Function.call() acceptă argumentele separat. În practică, după părerea mea, este mai convenabil să folosiți apply() .

Regula de apelare a funcției #3: Dacă doriți să suprascrieți valoarea acesteia fără a copia funcția într-un alt obiect, puteți utiliza myFunction.apply(obj) sau myFunction.call(obj) .

Constructori Nu mă voi opri în detaliu asupra declararii unor tipuri personalizate în JavaScript, dar cred că este necesar să vă reamintesc că nu există clase în JavaScript și orice tip definit de utilizator are nevoie de un constructor. În plus, este mai bine să declarați metode de tip personalizat folosind prototype , care este o proprietate a funcției de constructor. Să ne creăm propriul tip:
// declară funcția constructor ArrayMaker(arg1, arg2) ( this.someProperty = "nu contează"; this.theArray = [ this, arg1, arg2 ]; ) // declar metode ArrayMaker.prototype = ( someMethod: function () ( alert( "Apelat de someMethod"); getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker ("unu", "două"); var other = new ArrayMaker ("primul", "al doilea"); am.getArray(); // => [ am, „unu”, „doi” ]
Lucrul important în acest exemplu este prezența noului operator înainte de apelul funcției. Dacă nu ar fi, ar fi un apel global, iar proprietățile create în constructor ar aparține obiectului global. Nu avem nevoie de asta. În plus, constructorii de obicei nu returnează valori în mod explicit. Fără noul operator, constructorul ar returna nedefinit, cu el returnează acest lucru. Se consideră un stil bun de a numi constructorii cu majuscule; Acest lucru vă va aminti de necesitatea noului operator.

În caz contrar, codul din interiorul constructorului va fi probabil similar cu codul pe care l-ați scrie într-o altă limbă. Valoarea acestuia în acest caz este noul obiect pe care îl creați.

Regula de apelare a funcției #4: Când apelați o funcție cu noul operator, valoarea acestuia va fi un obiect nou creat de runtime JavaScript. Dacă această funcție nu returnează niciun obiect în mod explicit, acesta va fi returnat implicit.

Concluzie Sperăm că înțelegerea diferenței dintre diferitele moduri de a apela funcții vă va ajuta să vă îmbunătățiți codul JavaScript. Uneori, erorile legate de această valoare sunt greu de detectat, așa că este logic să le preveniți în avans.

Cele mai bune articole pe această temă