Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • OS
  • Programare functionala. Funcții în JavaScript

Programare functionala. Funcții în JavaScript

Funcții

Funcţie este un bloc de cod JavaScript care este definit o dată și poate fi executat sau apelat de mai multe ori. Este posibil să fiți deja familiarizați cu o funcție sub alt nume, cum ar fi o subrutină sau o procedură. Funcțiile pot avea parametri: o definiție de funcție poate include o listă de identificatori, care sunt numiți parametri și acționează ca variabile locale în corpul funcției.

La apelarea funcțiilor, acestora li se pot transmite valori sau argumente corespunzătoare parametrilor lor. Funcțiile își folosesc adesea argumentele pentru a evalua valoarea returnată, care este valoarea expresiei de apelare a funcției. Pe lângă argumente, la apelarea oricărei funcții, i se transmite o altă valoare care determină contextul apelului - valoarea din cuvântul cheie acest.

Funcțiile din JavaScript sunt obiecte și pot fi utilizate într-o varietate de moduri. De exemplu, funcțiile pot fi atribuite variabilelor și transmise altor funcții. Deoarece funcțiile sunt obiecte, este posibil să atribuiți valori proprietăților lor și chiar să le apelați metode.

JavaScript vă permite să creați definiții de funcții care sunt imbricate în alte funcții, iar astfel de funcții vor avea acces la toate variabilele prezente în domeniul de aplicare al definiției.

Definirea funcțiilor

Definiția funcției începe cu un cuvânt cheie funcţie urmate de urmatoarele componente:

Un identificator care definește numele funcției

Numele este o parte obligatorie a instrucțiunii de declarare a funcției: va fi folosit pentru a crea o nouă variabilă căreia îi va fi atribuit noul obiect funcție. Numele poate fi absent în expresiile de definire a funcției: dacă este prezent, numele se va referi la obiectul funcție doar în corpul funcției în sine.

O pereche de paranteze în jurul unei liste de zero sau mai mulți identificatori, separate prin virgule

Acești identificatori vor defini numele parametrilor funcției și pot fi utilizați ca variabile locale în corpul funcției.

O pereche de acolade cu zero sau mai multe instrucțiuni JavaScript înăuntru

Aceste instrucțiuni alcătuiesc corpul funcției: ele sunt executate de fiecare dată când funcția este apelată.

Următorul exemplu arată mai multe definiții de funcții ca instrucțiuni și expresii. Rețineți că definițiile de funcții ca expresii sunt utile numai dacă fac parte din expresii mai mari, cum ar fi atribuiri sau apeluri de funcții, care fac ceva cu o funcție nou declarată:

// Tipărește numele și valorile tuturor proprietăților funcției obiect obj printprops (obj) (pentru (var p în obj) console.log (p + ":" + obj [p] + "\ n"); ) // Calculează distanța dintre punctele (x1, y1) și (x2, y2) funcție distanță (x1, y1, x2, y2) (var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt ( dx * dx + dy * dy );) // Funcție recursivă (autointitulându-se) care calculează funcția factorială factorial (x) (dacă (x)

Rețineți că este posibil ca numele funcției să nu fie prezent în expresiile de definire a funcției. O instrucțiune de declarare a funcției declară de fapt o variabilă și îi atribuie un obiect funcție.

În schimb, o expresie de definiție a funcției nu declară o variabilă. Cu toate acestea, în expresiile de definiție, este permisă specificarea numelui funcției, ca în funcția de calculare a factorialului de mai sus, care poate fi necesar în corpul funcției pentru a se autodenomina. Dacă expresia definiției funcției include un nume, numele dat se va referi la obiectul funcției din domeniul de aplicare al acelei funcții. De fapt, numele funcției devine o variabilă locală, accesibilă doar în corpul funcției. În cele mai multe cazuri, numele funcției nu trebuie să fie specificat în expresiile de definiție, ceea ce face definițiile mai compacte.

Rețineți că majoritatea (dar nu toate) funcțiile din exemplu conțin o instrucțiune return. Instrucțiunea return încheie execuția funcției și returnează valoarea expresiei acesteia (dacă este specificată) programului apelant. Dacă nu există o expresie în instrucțiunea return, aceasta returnează nedefinit. Dacă nu există nicio instrucțiune return în funcție, interpretul va executa pur și simplu toate instrucțiunile din corpul funcției și va reveni nedefinit la programul apelant.

Majoritatea funcțiilor din exemplu evaluează o anumită valoare și folosesc o instrucțiune return pentru a returna acea valoare programului apelant. Funcția printprops () este ușor diferită în acest sens: sarcina sa este de a tipări numele proprietăților unui obiect. Nu trebuie să returneze nicio valoare, deci nu există nicio instrucțiune de returnare în funcție. Funcția printprops () va returna întotdeauna nedefinit. (Funcțiile care nu au o valoare returnată sunt uneori numite proceduri.)

Funcții de apelare

Codul programului care formează corpul funcției este executat nu în momentul în care funcția este definită, ci în momentul în care este apelată. Apelurile de funcții sunt efectuate folosind o expresie de apel. O expresie de apel constă dintr-o expresie de apel de funcție care returnează un obiect funcție, urmată de paranteze urmate de o listă cu zero sau mai multe expresii argument, separate prin virgule, în interior.

Dacă expresia de apel de funcție este o expresie de apel de proprietate - dacă funcția este o proprietate a unui obiect sau un element al unui tablou (adică o metodă) - atunci expresia de apel este o expresie de apel de metodă. Următorul fragment demonstrează câteva exemple de expresii obișnuite de apelare a funcției:

Elemente de imprimare ((x: 4, vârsta: 24)); var d = distanta (1,1,5,6); var f = factorial (5) / factorial (12); f = pătrat (5);

Când funcția este apelată, toate expresiile de argument (specificate între paranteze) sunt evaluate, iar valorile rezultate sunt utilizate ca argumente pentru funcție. Aceste valori sunt atribuite parametrilor ale căror nume sunt listate în definiția funcției. În corpul unei funcții, expresiile de apel de parametri returnează valorile argumentelor corespunzătoare.

Când este apelată o funcție normală, valoarea returnată a funcției devine valoarea expresiei de apelare. Dacă funcția revine când interpretul ajunge la sfârșit, valoarea returnată este nedefinită. Dacă o funcție revine ca rezultat al unei instrucțiuni return, valoarea expresiei care urmează instrucțiunii return este returnată sau nedefinită dacă instrucțiunea return nu are nicio expresie.

Metodă nu este altceva decât o funcție care este stocată ca proprietate a unui obiect. Dacă aveți o funcție func și un obiect obj, puteți defini o metodă pe obiectul obj numit metoda, așa cum se arată mai jos:

// Definiți un obiect și o funcție simplă var obj = (); function func (a, b) (return a + b;) // Adăugați metoda obj la obiectul obj.method = func; // Acum puteți numi această metodă var result = obj.method (4, 5);

Cel mai adesea, atunci când apelați metode, utilizați forma de accesare a proprietăților folosind operatorul punct, dar în același mod puteți utiliza forma de accesare a proprietăților folosind paranteze drepte. De exemplu, ambele dintre următoarele expresii sunt expresii de invocare a metodei:

Rezultat = obj.method (4, 5); rezultat = obj [„metoda”] (4, 5);

Argumentele și valoarea returnată a unui apel de metodă sunt tratate în același mod ca un apel de funcție obișnuit. Cu toate acestea, invocarea metodei are o diferență importantă: contextul de invocare. O expresie de acces la proprietate constă din două părți: un obiect (în acest caz, obj) și un nume de proprietate (metodă). În astfel de expresii de apel de metodă, obiectul obj devine contextul de apelare, iar corpul funcției se poate referi la acest obiect folosind cuvântul cheie this. De exemplu:

Var obj = (x: 0, y: 0, // Metoda adaugă: funcția (a, b) (this.x = a; this.y = b;), // O altă metodă sum: function () (return this .x + aceasta.y)); // Apelarea metodelor obj.add (15, 4); console.log (obj.sum ()); // 19

Metodele și acest cuvânt cheie sunt centrale pentru paradigma de programare orientată pe obiecte. Orice funcție folosită ca metodă primește de fapt un argument implicit - obiectul pe care a fost apelată. De obicei, metodele efectuează o anumită acțiune asupra unui obiect, iar sintaxa apelului de metodă reflectă în mod clar faptul că o funcție operează pe un obiect.

Notă: acesta este doar un cuvânt cheie, nu o variabilă sau un nume de proprietate. Sintaxa JavaScript nu permite alocarea de valori acestui element.

Argumente și parametrii funcției

În JavaScript, tipurile de parametri nu sunt specificate în definițiile funcției și nu se efectuează verificări de tip asupra valorilor argumentelor transmise atunci când funcțiile sunt apelate. De fapt, atunci când se apelează funcții în JavaScript, nici măcar numărul de argumente nu este verificat. Subsecțiunile de mai jos descriu ce se întâmplă atunci când numărul de argumente dintr-un apel de funcție este mai mic sau mai mare decât numărul de parametri declarați. Ele demonstrează, de asemenea, cum puteți verifica în mod explicit tipurile de argumente ale unei funcții dacă trebuie să vă asigurați că funcția nu este apelată cu argumente nevalide.

Argumente opționale

Când numărul de argumente dintr-un apel de funcție este mai mic decât numărul de parametri declarați, argumentele lipsă sunt nedefinite. Este adesea convenabil să scrieți funcții, astfel încât unele dintre argumente să fie opționale și să poată fi omise atunci când funcția este apelată. În acest caz, este de dorit să se prevadă posibilitatea de a atribui parametrilor care pot fi omisi valori implicite rezonabile. De exemplu:

// Adăugați numele enumerate // ale proprietăților obiectului obj în tabloul arr și returnați-l. Dacă argumentul // arr nu a fost transmis, creați și returnați o nouă funcție de matrice getPropertyNames (obj, / * opțional * / arr) (dacă (arr === nedefinit) arr =; // Dacă matricea nu este definită, creați una nouă pentru (var proprietate în obj) arr.push (proprietate); return arr;) // Această funcție poate fi apelată cu 1 sau 2 argumente: var a = getPropertyNames ((x: 1, y: 1)); // Obține proprietățile obiectului într-o nouă matrice getPropertyNames ((z: 5), a); // adaugă proprietăți ale noului obiect la această matrice console.log (a); // ["x", "y", "z"]

Rețineți că atunci când declarați funcții, argumentele opționale trebuie să încheie lista de argumente pentru a fi omise. Programatorul care va scrie un apel la funcția dvs. nu va putea să treacă al doilea argument și, în același timp, să îl omite pe primul: va fi forțat să treacă în mod explicit nedefinit în primul argument. Observați și comentariul / * opțional * / din definiția funcției, care subliniază faptul că parametrul este opțional.

Liste de argumente cu lungime variabilă

Dacă numărul de argumente dintr-un apel de funcție depășește numărul de nume de parametri, funcția este împiedicată să acceseze direct valorile nenumite. Soluția la această problemă oferă Obiectul argumentelor... În corpul funcției, identificatorul argumente se referă la obiectul Argumente prezent în apel. Obiectul Arguments este un obiect asemănător matricei care vă permite să preluați valorile transmise unei funcții după numerele lor, mai degrabă decât după nume.

Să presupunem că funcția a fost definită care necesită un argument, x. Dacă apelați această funcție cu două argumente, atunci primul va fi disponibil în interiorul funcției cu numele parametrului x sau ca argumente. Al doilea argument va fi disponibil doar ca argumente. În plus, ca și tablourile reale, argumentele au o proprietate de lungime care determină numărul de elemente care trebuie să conțină. Adică, în corpul func apelat cu două argumente, arguments.length este 2.

Obiectul Argumente poate fi folosit pentru o mare varietate de scopuri. Următorul exemplu arată cum să îl utilizați pentru a verifica dacă o funcție a fost apelată cu numărul corect de argumente, deoarece JavaScript nu va face asta pentru dvs.:

Funcția func (x, y, z) (// În primul rând, verifică dacă a fost transmis numărul corect de argumente dacă (arguments.length! = 3) (aruncă o nouă eroare ("Funcția func a fost apelată cu" + arguments.length + "argumente, dar 3. ");) // Și acum codul funcției în sine ...)

Rețineți că este adesea inutil să verificați numărul de argumente, ca în acest exemplu. Comportamentul implicit al interpretului JavaScript este excelent pentru majoritatea cazurilor: argumentele lipsă sunt înlocuite cu nedefinite, iar argumentele suplimentare sunt pur și simplu ignorate.

Obiectul Arguments ilustrează o caracteristică importantă a funcțiilor JavaScript: acestea pot fi scrise pentru a lua orice număr de argumente. Următoarea funcție preia orice număr de argumente și returnează valoarea celui mai mare dintre ele (funcția Math.max () încorporată se comportă în mod similar):

Funcția maxNumber () (var m = Number.NEGATIVE_INFINITY; // Buclă prin toate argumentele, găsiți și // stocați cel mai mare dintre ele pentru (var i = 0; im) m = argumente [i]; // Returnează cea mai mare returnare m ;) var cea mai mare = maxNumber (1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10000

Funcții ca aceasta, care pot lua un număr arbitrar de argumente, se numesc funcții variadice, funcții de aritate variabilă sau funcții varargs. Acest termen a apărut odată cu apariția limbajului de programare C.

Rețineți că funcțiile cu un număr variabil de argumente nu trebuie să fie apelabile cu o listă de argumente goală. Este perfect logic să folosiți obiectul arguments atunci când scrieți o funcție care se așteaptă să primească un număr fix de argumente numite necesare, urmate de un număr arbitrar de argumente opționale fără nume.

Rețineți că argumentele nu sunt de fapt o matrice - sunt un obiect Arguments. Fiecare obiect Arguments are elemente de matrice numerotate și o proprietate de lungime, dar din punct de vedere tehnic nu este o matrice. Mai bine să ne gândim la el ca la un obiect cu unele proprietăți numerotate.

Pe lângă elementele matricei sale, obiectul Arguments definește proprietăți apelatși apelant... Încercarea de a modifica valorile acestor proprietăți în modul strict ECMAScript 5 este garantată pentru a arunca o excepție TypeError. Cu toate acestea, în modul lax, standardul ECMAScript afirmă că proprietatea apelat se referă la funcția care se execută în prezent. Proprietatea apelantului nu este standard, dar este prezentă în multe implementări și se referă la funcția care a apelat-o pe cea curentă.

Proprietatea apelant poate fi folosită pentru a accesa stiva de apeluri, iar proprietatea apelant este utilă în special pentru apelarea recursiv a funcțiilor fără nume:

Var factorial = funcția (x) (dacă (x

Proprietăți și metode ale funcțiilor

Am văzut că funcțiile pot fi folosite ca valori în programele JavaScript. Operatorul typeof returnează șirul „funcție” pentru funcții, dar funcțiile din JavaScript sunt de fapt un tip special de obiect. Și din moment ce funcțiile sunt obiecte, ele au proprietăți și metode ca orice alt obiect. Există chiar și un constructor Function () care creează noi obiecte funcție. Următoarele subsecțiuni descriu proprietățile și metodele funcțiilor.

Proprietatea lungimii

În corpul funcției, proprietatea arguments.length determină numărul de argumente transmise funcției. Cu toate acestea, proprietatea de lungime a funcției în sine are o semnificație diferită. Această proprietate numai în citire returnează numărul de argumente pe care funcția se așteaptă să le primească - numărul de parametri declarați.

Următorul fragment definește o funcție numită check () care primește o serie de argumente de la o altă funcție. Compară proprietatea arguments.length (numărul de argumente transmise efectiv) cu proprietatea arguments.callee.length (numărul de argumente așteptate) pentru a determina dacă funcției i s-au transmis atâtea argumente cât se așteaptă. Dacă valorile nu se potrivesc, se face o excepție. Funcția de verificare () este urmată de funcția de testare func (), care demonstrează cum se utilizează funcția de verificare ():

// Această funcție folosește arguments.callee, deci // nu va funcționa în modul strict de verificare a funcției (args) (var actual = args.length; // Numărul real de argumente var așteptat = args.callee.length; // Argumente de număr așteptat dacă (actual! == așteptat) // Dacă nu se potrivesc, aruncați o nouă eroare ("așteptat:" + așteptat + "; primit" + actual);) funcția func (x, y, z) (/ / Verificați numărul de argumente așteptate și trecute efectiv verificați (argumente); // Acum executați restul funcției return x + y + z;)

Proprietate prototip

Orice funcție are o proprietate prototip care se referă la un obiect cunoscut sub numele de obiect prototip. Fiecare funcție are propriul său obiect prototip. Când o funcție este folosită ca constructor, obiectul nou creat moștenește proprietățile acelui obiect prototip.

Prototipurile și proprietatea prototipului au fost discutate în articolul anterior.

Apelați () și aplicați () metode

Metodele call () și apply () vă permit să apelați indirect o funcție ca și cum ar fi o metodă a unui alt obiect. Primul argument atât pentru call () cât și pentru apply () este obiectul pe care este apelată funcția; acest argument definește contextul apelului și devine valoarea cuvântului cheie this din corpul funcției. Pentru a apela func () (fără argumente) ca metodă de obj, puteți utiliza oricare dintre metodele de apel () sau aplicați ():

Func.call (obj); func.aplica (obj);

Oricare dintre aceste metode de apel este echivalentă cu următorul fragment (presupunând că obj nu are o proprietate numită m):

Obj.m = func; // Funcţionează temporar metoda obj obj.m (); // Numiți-o fără argumente. șterge obj.m; // Eliminați metoda temporară.

În modul strict ECMAScript 5, primul argument al metodelor call () și apply () devine această valoare, chiar dacă este o valoare simplă, nulă sau nedefinită. În ECMAScript 3 și modul non-strict, valorile nule și nedefinite sunt înlocuite cu obiectul global, iar valoarea simplă este înlocuită cu obiectul wrapper corespunzător.

Toate celelalte argumente ale metodei call () care urmează primului argument care specifică contextul apelului sunt transmise funcției apelate. Metoda apply () acționează ca metoda call (), cu excepția faptului că argumentele funcției sunt transmise ca o matrice. Dacă o funcție poate gestiona un număr arbitrar de argumente, metoda apply () poate fi utilizată pentru a apela acea funcție în contextul unei matrice de lungime arbitrară.

Următorul exemplu demonstrează o utilizare practică a metodei call ():

// Mai jos sunt două funcții care afișează proprietățile și // valorile proprietăților unui obiect arbitrar. Metoda de afișare // sunt transmise ca argument func funcția print1 (func, obj) (pentru (n în obj) func (n + ":" + obj [n]);) function print2 (func, objDevice, obj) ( pentru ( n în obj) func.call (objDevice, n + ":" + obj [n]);) var obj = (x: 5, y: 10); print2 (document.write, document, obj); // Funcționează corect print2 (console.log, console, obj); print1 (document.write, obj); // O excepție de invocare ilegală va fi aruncată deoarece print1 (console.log, obj); // este imposibil să apelați aceste metode fără un obiect context

Metoda Bind ().

Metoda bind () a apărut pentru prima dată în ECMAScript 5, dar este ușor de imitat în ECMAScript 3. După cum sugerează și numele, scopul principal al metodei bind () este de a lega o funcție la un obiect. Dacă apelați metoda bind () a func și îi transmiteți obiectul obj, va returna o nouă funcție. Apelarea noii funcție (ca o funcție normală) va apela funcția originală func ca metodă de obj. Orice argumente transmise noii funcție vor fi transmise funcției inițiale. De exemplu:

// Funcția de a lega funcția func (y) (return this.x + y;) var obj = (x: 1); // Obiectul de legat la var g = func.bind (obj); // Apelarea g (x) va apela obj.func (x)

Acest mod de legare este ușor de implementat în ECMAScript 3, după cum se arată mai jos:

// Returnează o funcție care apelează func ca metodă de obj // și îi transmite toate argumentele sale function bind (func, obj) (dacă (func.bind) return func.bind (obj); // Folosește metoda bind, dacă este prezent, altfel returnează funcția () (// Altfel se leagă ca mai jos return func.apply (obj, argumente););)

Metoda bind () din ECMAScript 5 nu leagă doar o funcție la un obiect. De asemenea, face aplicare parțială: în plus față de această valoare, toate argumentele transmise la bind () după primul argument vor fi legate. Aplicarea parțială este o tehnică comună în programarea funcțională și uneori este numită curry.

Articolul este în construcție!

Un articol în care vom lua în considerare ce este o funcție, precum și versiunea tradițională (clasică) a lucrului cu ea. În plus, vom analiza care sunt argumentele (parametrii) funcției și returnarea operatorului.

Ce este o funcție?

O funcție este unele set de instructiuni căruia i se poate da un nume și apoi face referire la el cu acest nume de oriunde în program.

Un exemplu clasic de utilizare a unei funcții. Pagina web are cod JavaScript, oarecare fragment în care se repetă de mai multe ori... Pentru a evita acest lucru, puteți modelați acest fragment ca o funcție, A apoi sună-lîn locurile potrivite din cod după denumirea acestei funcţii. Apelarea acestei funcții va însemna urmând instrucțiunile situat în el.

Cum pot organiza execuția unei sarcini în JavaScript folosind funcții? Pentru a face acest lucru, de obicei fac acest lucru:

  • împărțiți sarcina în părțile sale componente (subsarcini);
  • subsarcinile sunt formalizate prin funcții;
  • dezvolta codul principal folosind un apel la functiile generate.

Ca urmare, un astfel de program devine mai structurat. Este mai ușor să faceți diverse modificări și să adăugați noi funcții.

Declarație de funcție și apel

Operațiile cu funcții în JavaScript pot fi împărțite în 2 pași:

  • declarație (creare) funcții.
  • invocare (execuție) această funcție.

Declarație de funcție. Crearea unei funcții în JavaScript începe prin scrierea cuvântului cheie al funcției, urmat de numele funcției, apoi între paranteze x, dacă este necesar. parametrii sunt enumerați urmată de instrucţiuni care sunt cuprinse între bretele.

// declarația funcției someName funcția someName () (alertă ("Ați apelat funcția someName!");) JavaScript - Sintaxa de declarare a funcției

Funcțiile de acest fel în JavaScript sunt numite declarație de funcție... Pe lângă acest tip, JavaScript distinge și funcții expresie de definire a funcțieiși expresia funcției săgeată.

Formarea unui nume de funcție urmează aceleași reguli ca și numele unei variabile. Acestea. poate conține litere, cifre (0-9), semne „$” și „_”. Este recomandat să folosiți doar litere din alfabetul englez (a-z, A-Z) ca litere. Numele funcției, precum și numele variabilei, nu pot începe cu o cifră.

O funcție poate avea oricât de mulți parametri doriți, sau deloc. Parantezele sunt indicate în orice caz. Dacă există mai mulți parametri, atunci aceștia trebuie separați între ei folosind o virgulă. Parametrii funcției sunt adresați prin numele lor.

Set de instructiuni, cuprins între acolade este codul funcției care va fi executat atunci când este apelat.

Apel de funcție. Funcție declarată de propria ei nu va fi executat... Pentru a-l porni, trebuie să îl suni. Funcția este apelată prin specificarea numelui și a două paranteze. Argumentele sunt furnizate între paranteze, dacă este necesar.

// apelează funcția dată în exemplul anterior someName (); JavaScript - Sintaxă a apelurilor de funcție

Este o funcție din JavaScript un obiect?

Funcțiile din JavaScript sunt obiecte.În JavaScript, totul este în general un obiect, cu excepția celor șase tipuri de date primitive. Și dacă funcția este un obiect, atunci o referință la aceasta poate fi salvată într-o variabilă.

// declarație funcție someName function someName () (alertă ("Ați apelat funcția someName!");) var reference = someName;

După aceea, puteți apela funcția astfel:

Referință ();

Parametrii și argumentele funcției

Argumente ale funcției- acestea sunt valorile care sunt transmise funcției în etapa apelării acesteia. Separați argumentele unul de celălalt cu o virgulă.

// apelează funcția sayWelcome cu două argumente transmise sayWelcome ("Ivan", "Ivanov"); // un alt apel la funcția sayWelcome cu două argumente sayWelcome ("Petru", "Petrov");

Parametrii funcției Este una dintre modalitățile din JavaScript prin care vă puteți referi la argumente dintr-o funcție. Parametrii funcției în stadiul declarării acesteia sunt descriși în paranteze.

Cu alte cuvinte parametrii funcției- acestea sunt variabile locale care sunt create automat în etapa de pornire a funcției. Ca valori, parametrii primesc argumentele corespunzătoare transmise funcției în momentul apelării acesteia. Parametrii pot fi accesați doar în cadrul acestei funcții, în afara acesteia nu există.

// declarația funcției sayWelcome, care are doi parametri funcție sayWelcome (userFirstName, userLastName) (// o instrucțiune care afișează valorile parametrilor „userFirstName” și „userLastName” în consola console.log („Welcome, " + userLastName + "" + userFirstName );)

În JavaScript, la apelarea unei funcții numărul de argumente nu trebuie să fie același cu numărul de parametri... Parametrii care nu au fost setați la o valoare atunci când sunt apelați vor fi nedefiniți.

De exemplu, să apelăm funcția din exemplul de mai sus fără a specifica unul sau doi parametri:

// apelează funcția sayWelcome și îi trece un argument sayWelcome ("Petru"); // Bun venit nedefinit Peter // apelează funcția sayWelcome fără a-i transmite argumente sayWelcome (); // Bun venit, undefined undefined

Un exemplu de funcție care va imprima pur și simplu argumentele transmise către consola browserului:

// declararea funcției funcția outputParam (param1, param2, param3) (console.log (param1 + ";" + param2 + ";" + param3);) // apelează la funcția outputParam cu un număr diferit de parametri transmisi acesteia outputParam ("Ploaie", "Zăpadă", "Ceață"); // Ploaie; Zăpadă; Ieșire ceațăParam (17); // 17; nedefinit; outputParam nedefinit (24.33); // 24; 33; outputParam nedefinit (); // nedefinit; nedefinit; nedefinit

Un alt mod de a face referire la argumente dintr-o funcție este de a folosi obiectul argumente speciale. Argumentele sunt accesate prin argumente în același mod ca elementele unui tablou obișnuit, de exemplu. după numerele lor de serie. Astfel, argumentul este primul argument, argumentele este al doilea și așa mai departe.

// declarație funcție sum funcția sum (num1, num2) (/ * num1 sau argumente - obține valoarea 1 argument num2 sau argumente - obține valoarea argumentului 2 * / var sum1 = num1 + num2, sum2 = argumente + argumente; returnează „Suma, primită prin calea 1 este egală cu „+ sum1 +”; suma obținută prin calea 2 este egală cu „+ sum2;) / * afișează rezultatul funcției sumă în consola 7 - primul argument (puteți faceți referire la el atât prin numele num1 cât și folosind argumente) 4 - al doilea argument (vă puteți referi la el atât prin numele num2, cât și folosind argumente) * / console.log (sum (7,4));

Principala diferență dintre aceste metode este că prima dintre ele vă permite să accesați doar acele argumente care au fost denumite în etapa de declarare a funcției. A doua metodă vă permite să obțineți valoarea oricărui argument, chiar dacă nu are nume (prin număr ordinal). Această caracteristică a limbajului JavaScript vă permite să creați funcții flexibile versatile.

Pe lângă primirea argumentelor, obiectul arguments vă permite să știți și câte argumente există. Acest lucru se face folosind proprietatea lungime.

Iterați peste argumente transmisă funcției, puteți, de exemplu, să utilizați o buclă pentru sau pentru ... de buclă.

// declarația funcției sum funcția sum () (var i = 0; console.log ("Ieșirea tuturor argumentelor folosind o buclă for"); for (i; i< arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

O funcție care imprimă pe consolă toate argumentele transmise acesteia și numărul lor:

// funcția de declarare a funcției myFunction () (var i; console.log ("Numărul de parametri trecuți =" + arguments.length); // repetare peste toți parametrii folosind bucla for for (i = 0; i< arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

O funcție care adaugă toate argumentele transmise acesteia (numărul acestora nu este cunoscut în prealabil):

// declarația funcției var myCalc = function () (// iterează peste toți parametrii folosind o buclă for var i, sum = 0; for (i = 0; i lt; arguments.length; i ++) (sum + = argumente) [i] ;) // returnează suma ca rezultat returnează suma;) // apelează funcția (ieșire către consolă) console.log (myCalc (4, 20, 17, -6));

Ca rezultat, folosind obiectul arguments, puteți implementa în corpul funcției:

  • verificarea numărului de argumente transmise;
  • câți parametri sunt procesați.

Pe lângă funcția în sine, alte funcții care se află în ea au și acces la argumentele care îi sunt transmise în faza de apel.

Funcția mainF (p1, p2) (funcția childF () (console.log ("p1 =" + p1 + "; p2 =" + p2);) childF ();) mainF (3, 5); // p1 = 3; p2 = 5 mainF (4, 7); // p1 = 4; p2 = 7

Valoarea implicită a parametrului

Din ECMAScript 2015 (6) parametrul funcției puteți seta valoarea pe care o va avea implicit.

De exemplu, să setăm parametrul „culoare” la valoarea sa implicită egală cu „# 009688”:

Funcția setBGColor (culoare = "# 009688") (document.body.style.backgroundColor = culoare;) setBGColor (); // culoarea de fundal va fi # 009688 setBGColor ("roșu"); // culoarea de fundal va fi roșie

Înainte de ECMAScript 2015, puteai seta un parametru la o valoare implicită, de exemplu, era așa:

Funcția setBGColor (culoare) (culoare = culoare! == nedefinit? Culoare: "# 009688"; // setați culoarea implicită la "# 009688" document.body.style.backgroundColor = culoare;)

Parametrii de odihnă

Dacă, atunci când apelați o funcție, îi transmiteți mai multe argumente decât are parametrii, atunci puteți obține restul folosind așa-numitul patametre de odihnă... Această caracteristică a apărut în limbaj începând cu ECMAScript 2015.

// ... nums sunt parametrii rămași, care pot fi accesați în acest caz prin numele nums function doMath (mathAction, ... nums) (var rezultat = 0; nums.forEach (funcție (valoare) (switch (mathAction) ) ( caz "sum": rezultat + = valoare; break; case "sumCube": rezultat + = valoare ** 3; break; caz "sumSquare": rezultat + = valoare ** 2; break; deafult: rezultat = 0; )) ) returnează rezultat;) console.log (doMath ("suma", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log (doMath ("sumSquare", 1, 4)); // 17 (1 ^ 2 + 4 ^ 2) console.log (doMath ("sumCube", 3, 2, 4)); // 99 (3 ^ 3 + 2 ^ 3 + 4 ^ 3)

Declarație de returnare

Instrucțiunea return are scopul de a returna valoarea sau rezultatul evaluării expresiei funcției curente. Valoarea sau expresia trebuie separată de returnare printr-un spațiu. În plus, instrucțiunea return încheie execuția funcției, adică. toate instrucțiunile care le urmează nu vor fi executate.

O funcție JavaScript returnează întotdeauna un rezultat, indiferent dacă instrucțiunea return este utilizată sau nu.

// funcția care returnează funcția de rezultat sayWelcome (userFirstName, userLastName) (dacă ((! userFirstName) || (! userLastName)) returnează „Bun venit, utilizator anonim”; altfel returnează „Welcome,” + userLastName + „” + userFirstName ; ) // declarație variabilă person var person; // atribuiți rezultatul funcției sayWelcome variabilei persoană persoană = sayWelcome ("Ivan", "Ivanov"); // imprimă valoarea variabilei în consola console.log (persoană); // O instrucțiune care va imprima pe consolă rezultatul funcției sayWelcome console.log (sayWelcome ("Peter", "Petrov")); // O instrucțiune care va imprima pe consolă rezultatul funcției sayWelcome console.log (sayWelcome ("Sidorov")); JavaScript - Funcție cu validare a parametrilor

O funcție JavaScript, ca rezultat al execuției sale, returnează întotdeauna un rezultat, chiar dacă nu este definit în mod explicit folosind instrucțiunea return. Acest rezultat este nedefinit.

// 1. o funcție care nu returnează nicio funcție de rezultat sayWelcome (userFirstName, userLastName) (console.log ("Welcome," + userLastName + "" + userFirstName);) // încercați să obțineți rezultatul de la o funcție care nu nu returnează nimic consola .log (spune Bun venit ("Ivan", "Ivanov")); // 2. o funcție care conține o instrucțiune return fără o funcție de valoare sayDay (day) (ziua = „Azi,” + zi; return; // această instrucțiune nu va fi executată, deoarece vine după instrucțiunea return console.log ( zi) ;) // încercați să obțineți rezultatul dintr-o funcție care conține o instrucțiune return fără o valoare console.log (sayDay ("21 februarie 2016")); JavaScript - Obțineți o valoare dintr-o funcție care nu returnează nimic

Același rezultat va fi obținut dacă nu specificați o valoare de returnare pentru instrucțiunea de returnare.

Supraîncărcarea funcției în JavaScript

Supraîncărcarea funcției în programare este capacitatea de a declara mai multe funcții cu același nume în același domeniu. Astfel de funcții diferă unele de altele prin tipul și numărul de argumente. Fiecare funcție are propria sa logică de program. Supraîncărcarea funcției este utilizată astfel încât acțiuni similare să poată fi efectuate folosind un singur nume de funcție.

JavaScript nu acceptă supraîncărcarea funcțiilor, așa cum este, de exemplu, în limbaje asemănătoare C. Acestea. JavaScript nu poate crea mai multe funcții cu același nume în același domeniu.

Funcționalități similare pot fi implementate în JavaScript utilizând următorii pași:

  • Pentru a verifica dacă un argument este transmis sau nu, utilizați o condiție cu verificarea valorii sale pentru nedefinit.
  • Utilizați proprietatea lungimii argumente a obiectului pentru a verifica numărul de argumente transmise unei funcții.
  • Utilizați operatorii typeof sau instanceof pentru a afla tipul valorii argumentului transmis.
  • Pentru a lucra cu un număr variabil de argumente, utilizați obiectul arguments.
  • Începând cu ECMAScript6, puteți furniza valori implicite pentru argumente.

De exemplu, să creăm o funcție care poate fi apelată cu unul sau două argumente:

// declararea unei funcții care schimbă culoarea de fundal a elementelor funcția setBgColor (bgColor, elemente) (// dacă parametrul elementelor nu este specificat la apelarea if (elements === nedefinit) (// apoi echivalează valoarea sa "div" elements = "div ";) // obțineți toate elementele elemente = $ (elemente); // repetați peste toate elementele și setați-le la culoarea de fundal specificată elements.each (funcție () ($ (this) .css (" fundal -color ", bgColor) ;));) / * Apelați funcția setBgColor cu un singur parametru. pentru că Parametrul 2 nu este specificat, atunci această funcție va schimba culoarea de fundal a tuturor elementelor div * / SetBgColor ("verde"); / * Apelați funcția setBgColor cu 2 parametri. pentru că parametrul 2 este specificat, atunci această funcție va schimba culoarea de fundal numai a elementelor butoanelor * / SetBgColor ("# ff0000", "button");

Să facem câteva modificări codului de mai sus. Și anume, să specificăm valoarea implicită pentru al doilea parametru:

// declararea unei funcții care schimbă culoarea de fundal a elementelor // parametrul elementelor este setat la "div" în mod implicit, funcția setBgColor (bgColor, elements = "div") (// obține toate elementele elemente = $ (elemente); / / repetă peste toate elementele și setează-le la elementele de culoare de fundal specificate.each (funcție () ($ (this) .css ("background-color", bgColor);));) // apelează funcția setBgColor, specificând una parametru setBgColor ("verde"); // apelează funcția setBgColor, specificând 2 parametri setBgColor ("# ff0000", "button");

Un exemplu despre cum în JavaScript puteți implementa o funcție „supraîncărcată” care calculează numărul de calorii de care are nevoie o persoană pe zi:

// descrierea funcției funcția countCal (sex, înălțime) (// parametri: sex (gen) și înălțime (înălțime) var rezultat; if ((sex === 0) || (sex === „bărbat”)) ( rezultat = (înălțime - 100) * 20;) else if ((sex === 1) || (sex === „femeie”)) (rezultat = (înălțime - 105) * 19;) dacă (rezultat) ( // argumente - nivelul de activitate if (argumente) (rezultat * = argumente;) console.log ("Număr de kcal pentru viața normală:" + rezultat);) else (console.log ("Sunt specificați parametrii nevalidi");) ) / * apelarea unei funcții și transmiterea a 2 argumente acesteia (1 este „om”, poate fi accesată folosind numele sex și argumente; 2 este valoarea 185, poate fi accesată folosind numele sex și argumente) * / countCal („om”, 185); / * apelarea funcției și trecerea acesteia a 3 parametri, deși sunt doar 2 în descrierea funcției (în acest caz, puteți obține valoarea a 3 parametri doar ca argumente) * / countCal (0, 185, 2);

Recursiune

Recursiunea este un apel în interiorul corpului al unei anumite funcții către sine.

Un apel de funcție este de obicei efectuat în funcție de modul în care este declarat prin nume sau printr-o variabilă care conține o referință la această funcție.

Function fact (n) (daca (n === 1) (return 1;) return fact (n-1) * n;) console.log (fact (5)); // 120

Puteți apela o funcție în corpul său nu numai după nume, ci și folosind proprietatea apelat a obiectului arguments. Dar este mai bine să nu folosiți această proprietate, deoarece este învechit. În plus, în modul strict, nu funcționează deloc.

Ce sunt funcțiile încorporate (standard)?

JavaScript are un set imens de funcții încorporate (standard). Aceste funcții sunt deja descrise în motorul browserului însuși. Aproape toate sunt metode ale unui obiect.

De exemplu, pentru a apela funcția (metoda) încorporată de alertă, nu trebuie să fie declarată în prealabil. Este deja descris în browser. Metoda de alertă este apelată prin specificarea unui nume, a parantezelor și a unui argument în cadrul acestora. Această metodă este concepută pentru a afișa un mesaj pe ecran sub forma unei casete de dialog. Mesajul text este preluat din valoarea parametrului acestei funcții.

// apelează funcția de alertă ("Un text"); JavaScript - Apelarea funcției de alertă

Funcțiile sunt unul dintre elementele fundamentale ale JavaScript. O funcție este o procedură JavaScript - un set de instrucțiuni care efectuează o sarcină sau calculează o valoare. Pentru a utiliza o funcție, trebuie să o definiți undeva în domeniul din care doriți să o apelați.

A metodă este o funcție care este o proprietate a unui obiect. Citiți mai multe despre obiecte și metode în Lucrul cu obiecte.

Funcții de apelare

Definirea unei funcții nu o execută. Definirea funcției pur și simplu denumește funcția și specifică ce trebuie făcut atunci când funcția este apelată. Apel funcția realizează efectiv acțiunile specificate cu parametrii indicați. De exemplu, dacă definiți pătratul funcției, îl puteți numi după cum urmează:

pătrat (5);

Instrucțiunea precedentă apelează funcția cu un argument de 5. Funcția își execută instrucțiunile și returnează valoarea 25.

Funcțiile trebuie să fie în domeniul de aplicare atunci când sunt apelate, dar declarația funcției poate fi ridicată (apare sub apelul în cod), ca în acest exemplu:

Console.log (pătrat (5)); / * ... * / funcție pătrat (n) (întoarce n * n;)

Sfera de aplicare a unei funcții este funcția în care este declarată, sau întregul program dacă este declarat la nivelul superior.

Notă: Acest lucru funcționează numai atunci când definiți funcția folosind sintaxa de mai sus (adică funcția funcName () ()). Codul de mai jos nu va funcționa. Aceasta înseamnă că funcția de ridicare funcționează numai cu declararea funcției și nu cu expresia funcției.

Console.log (pătrat); // pătratul este ridicat cu o valoare inițială nedefinită. console.log (pătrat (5)); // TypeError: pătratul nu este o funcție var pătrat = funcție (n) (return n * n;)

Argumentele unei funcții nu se limitează la șiruri și numere. Puteți trece obiecte întregi unei funcții. Funcția show_props () (definită în) este un exemplu de funcție care ia un obiect ca argument.

O funcție se poate autodenomina. De exemplu, iată o funcție care calculează factoriali recursiv:

Funcția factorială (n) (dacă ((n === 0) || (n === 1)) returnează 1; altfel returnează (n * factorial (n - 1));)

Apoi, puteți calcula factorii de la unu la cinci după cum urmează:

Var a, b, c, d, e; a = factorial (1); // a obține valoarea 1 b = factorial (2); // b obține valoarea 2 c = factorial (3); // c obține valoarea 6 d = factorial (4); // d obține valoarea 24 e = factorial (5); // e primește valoarea 120

Există și alte moduri de a apela funcții. Există adesea cazuri în care o funcție trebuie apelată dinamic, sau numărul de argumente pentru o funcție variază sau în care contextul apelului funcției trebuie setat la un obiect specific determinat în timpul execuției. Se pare că funcțiile sunt, ele însele, obiecte, iar aceste obiecte au, la rândul lor, metode (vezi obiectul Funcție). Una dintre acestea, metoda aplica () poate fi folosită pentru a atinge acest obiectiv.

Domeniul de aplicare a funcției

Variabilele definite în interiorul unei funcții nu pot fi accesate de oriunde în afara funcției, deoarece variabila este definită doar în domeniul de aplicare al funcției. Cu toate acestea, o funcție poate accesa toate variabilele și funcțiile definite în domeniul în care este definită. Cu alte cuvinte, o funcție definită în domeniul global poate accesa toate variabilele definite în domeniul global. O funcție definită în interiorul unei alte funcții poate accesa, de asemenea, toate variabilele definite în funcția sa părinte și orice altă variabilă la care funcția părinte are acces.

// Următoarele variabile sunt definite în domeniul global var num1 = 20, num2 = 3, name = "Chamahk"; // Această funcție este definită în funcția global scope multiply () (return num1 * num2;) multiplica (); // Returnează 60 // Un exemplu de funcție imbricată, funcție getScore () (var num1 = 2, num2 = 3; function add () (return name + "scored" + (num1 + num2);) return add ();) getScore (); // Returnează „Chamahk a marcat 5”

Domeniul de aplicare și stiva de funcții

Recursiune

O funcție se poate referi și se poate autodenomina. Există trei moduri prin care o funcție se referă la ea însăși:

  1. numele funcției
  2. o variabilă în domeniul de aplicare care se referă la funcție

De exemplu, luați în considerare următoarea definiție a funcției:

Var foo = bara de funcții () (// instrucțiunile merg aici);

În corpul funcției, următoarele sunt toate echivalente:

  1. bar ()
  2. argumente.calee ()
  3. prost ()

O funcție care se numește singură se numește a functie recursiva... În unele moduri, recursiunea este analogă cu o buclă. Ambele execută același cod de mai multe ori și ambele necesită o condiție (pentru a evita o buclă infinită, sau mai degrabă, recursiunea infinită în acest caz). De exemplu, următoarea buclă:

Var x = 0; în timp ce (x< 10) { // "x < 10" is the loop condition // do stuff x++; }

poate fi convertit într-o funcție recursivă și un apel la acea funcție:

Bucla de funcții (x) (dacă (x> = 10) // „x> = 10” este condiția de ieșire (echivalent cu „! (X< 10)") return; // do stuff loop(x + 1); // the recursive call } loop(0);

Cu toate acestea, unii algoritmi nu pot fi simple bucle iterative. De exemplu, obținerea tuturor nodurilor unei structuri arborescente (de exemplu, DOM) se face mai ușor folosind recursiunea:

Funcția walkTree (nod) (dacă (nodul == null) // return; // face ceva cu nodul pentru (var i = 0; i< node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }

În comparație cu bucla de funcție, fiecare apel recursiv în sine face multe apeluri recursive aici.

Este posibil să convertiți orice algoritm recursiv într-unul nerecursiv, dar adesea logica este mult mai complexă și pentru a face acest lucru necesită utilizarea unei stive. De fapt, recursiunea în sine folosește o stivă: stiva de funcții.

Comportamentul asemănător stivei poate fi văzut în următorul exemplu:

Funcția foo (i) (dacă (i< 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3

Funcții imbricate și închideri

Puteți imbrica o funcție într-o funcție. Funcția imbricată (internă) este privată pentru funcția care o conține (exterioară). De asemenea formează a închidere... O închidere este o expresie (de obicei o funcție) care poate avea variabile libere împreună cu un mediu care leagă acele variabile (care „închide” expresia).

Deoarece o funcție imbricată este o închidere, aceasta înseamnă că o funcție imbricată poate „moșteni” argumentele și variabilele funcției care le conține. Cu alte cuvinte, funcția interioară conține domeniul de aplicare al funcției exterioare.

  • Funcția interioară poate fi accesată numai din instrucțiunile din funcția exterioară.
  • Funcția interioară formează o închidere: funcția interioară poate folosi argumentele și variabilele funcției exterioare, în timp ce funcția exterioară nu poate folosi argumentele și variabilele funcției interioare.

Următorul exemplu arată funcții imbricate:

Funcția addSquares (a, b) (funcție pătrat (x) (întoarce x * x;) returnează pătrat (a) + pătrat (b);) a = addSquares (2, 3); // returnează 13 b = addSquares (3, 4); // returnează 25 c = addSquares (4, 5); // returnează 41

Deoarece funcția interioară formează o închidere, puteți apela funcția exterioară și puteți specifica argumente atât pentru funcția exterioară, cât și pentru cea interioară:

Function outside (x) (function inside (y) (retur x + y;) return inside;) fn_inside = exterior (3); // Gândește-te ca: dă-mi o funcție care adaugă 3 la orice dai // ​​il rezultat = fn_inside (5); // returnează 8 rezultat1 = exterior (3) (5); // returnează 8

Păstrarea variabilelor

Observați cum x este păstrat atunci când interiorul este returnat. O închidere trebuie să păstreze argumentele și variabilele în toate domeniile la care face referire. Deoarece fiecare apel oferă argumente potențial diferite, este creată o nouă închidere pentru fiecare apel către exterior. Memoria poate fi eliberată doar atunci când interiorul returnat nu mai este accesibil.

Acest lucru nu este diferit de stocarea referințelor în alte obiecte, dar este adesea mai puțin evident deoarece nu se setează referințele direct și nu le poate inspecta.

Funcții multi-imbricate

Funcțiile pot fi imbricate multiple, de ex. o funcție (A) care conține o funcție (B) care conține o funcție (C). Ambele funcții B și C formează închideri aici, deci B poate accesa A și C poate accesa B. În plus, deoarece C poate accesa B care poate accesa A, C poate accesa și A. Astfel, închiderile pot conține mai multe domenii; ele conţin în mod recursiv domeniul de aplicare al funcţiilor care îl conţin. Aceasta se numește înlănțuirea domeniului de aplicare... (De ce se numește „înlănțuire” va fi explicat mai târziu.)

Luați în considerare următorul exemplu:

Funcția A (x) (funcția B (y) (funcția C (z) (consola.log (x + y + z);) C (3);) B (2);) A (1); // înregistrează 6 (1 + 2 + 3)

În acest exemplu, C accesează B „s y și A” s x. Acest lucru se poate face deoarece:

  1. B formează o închidere care include A, adică B poate accesa argumentele și variabilele lui A.
  2. C formează o închidere care include B.
  3. Deoarece închiderea B include A, închiderea C include A, C poate accesa ambele B și Argumentele și variabilele lui A. Cu alte cuvinte, C lanţuri domeniile B și A în această ordine.

Reversul, însă, nu este adevărat. A nu poate accesa C, deoarece A nu poate accesa niciun argument sau variabilă a lui B, din care C este o variabilă. Astfel, C rămâne privat doar pentru B.

Conflicte de nume

Când două argumente sau variabile din domeniul de aplicare al unei închideri au același nume, există a conflict de nume... Mai multe domenii interioare au prioritate, astfel încât domeniul cel mai interior are cea mai mare prioritate, în timp ce domeniul cel mai exterior are cea mai mică. Acesta este lanțul domeniului de aplicare. Primul din lanț este cel mai interior, iar ultimul este cel mai exterior. Luați în considerare următoarele:

Function outside () (var x = 5; function inside (x) (retur x * 2;) return inside;) outside () (10); // returnează 20 în loc de 10

Conflictul de nume are loc la instrucțiunea return x și este între interiorul „parametrului x și exteriorul” variabilei x. Lanțul de acoperire aici este (în interior, în exterior, obiect global). Prin urmare, în interiorul „s x are prioritate față de exterior” s x, iar 20 (în interiorul „s x) este returnat în loc de 10 (în afara” s x).

Închideri

Închiderile sunt una dintre cele mai puternice caracteristici ale JavaScript. JavaScript permite imbricarea funcțiilor și acordă funcției interioare acces deplin la toate variabilele și funcțiile definite în interiorul funcției exterioare (și toate celelalte variabile și funcții la care funcția externă are acces). Cu toate acestea, funcția exterioară nu are acces la variabilele și funcțiile definite în interiorul funcției interioare. Aceasta oferă un fel de încapsulare pentru variabilele funcției interioare. De asemenea, deoarece funcția interioară are acces la sfera funcției exterioare, variabilele și funcțiile definite în funcția exterioară vor trăi mai mult decât durata execuției funcției exterioare, dacă funcția interioară reușește să supraviețuiască dincolo de durata de viață a funcției exterioare. funcţie. O închidere este creată atunci când funcția interioară este într-un fel pusă la dispoziție oricărui scop din afara funcției exterioare.

Var pet = funcție (nume) (// Funcția exterioară definește o variabilă numită „nume” var getName = funcție () (return name; // Funcția interioară are acces la variabila „nume” a funcției externe //) return getName; // Returnează funcția interioară, expunând-o astfel la domenii exterioare) myPet = animal de companie ("Vivie"); animalul meu (); // Returnează „Vivie”

Poate fi mult mai complex decât codul de mai sus. Poate fi returnat un obiect care conține metode de manipulare a variabilelor interioare ale funcției exterioare.

Var createPet = function (nume) (var sex; return (setName: function (newName) (nume = newName;), getName: function () (return name;), getSex: function () (return sex;), setSex: funcția (newSex) (dacă (tip de newSex === „șir” && (newSex.toLowerCase () === „masculin” || newSex.toLowerCase () === „femeie”)) (sex = newSex;)) )) var pet = createPet ("Vivie"); pet.getName (); // Vivie pet.setName ("Oliver"); pet.setSex („mascul”); pet.getSex (); // animal de companie masculin.getName (); // Oliver

În codul de mai sus, variabila nume a funcției exterioare este accesibilă funcțiilor interioare și nu există altă modalitate de a accesa variabilele interioare decât prin intermediul funcțiilor interioare. Variabilele interioare ale funcțiilor interioare acționează ca depozite sigure pentru argumentele și variabilele exterioare. Ei dețin date „persistente” și „încapsulate” pentru ca funcțiile interioare să lucreze. Funcțiile nici nu trebuie să fie atribuite unei variabile sau să aibă un nume.

Var getCode = (funcție () (var apiCode = "0] Eal (eh & 2"; // Un cod pe care nu dorim ca cei din afară să-l poată modifica... return function () (return apiCode;);)) () ; getCode (); // Returnează apiCode

Există, totuși, o serie de capcane la care trebuie să fiți atenți atunci când utilizați dispozitivele de închidere. Dacă o funcție închisă definește o variabilă cu același nume cu numele unei variabile din domeniul extern, nu există nicio modalitate de a face referire la variabila din domeniul extern din nou.

Var createPet = funcția (nume) (// Funcția exterioară definește o variabilă numită „nume". Return (setName: funcție (nume) (// Funcția inclusă definește și o variabilă numită „nume". Nume = nume; // Cum accesăm „numele” definit de funcția exterioară?)))

Folosind obiectul arguments

Argumentele unei funcții sunt menținute într-un obiect asemănător matricei. În cadrul unei funcții, puteți adresa argumentele transmise acesteia după cum urmează:

Argumente [i]

unde i este numărul ordinal al argumentului, începând de la zero. Deci, primul argument transmis unei funcții ar fi argumente. Numărul total de argumente este indicat prin argumente.lungime.

Folosind obiectul arguments, puteți apela o funcție cu mai multe argumente decât este declarat formal că acceptă. Acest lucru este adesea util dacă „nu știți dinainte câte argumente vor fi transmise funcției. Puteți utiliza arguments.length pentru a determina numărul de argumente transmise efectiv funcției și apoi accesați fiecare argument folosind obiectul arguments.

De exemplu, luați în considerare o funcție care concatenează mai multe șiruri. Singurul argument formal pentru funcție este un șir care specifică caracterele care separă elementele de concatenat. Funcția este definită după cum urmează:

Funcția myConcat (separator) (var rezultat = ""; // inițializează lista var i; // iterează prin argumente pentru (i = 1; i< arguments.length; i++) { result += arguments[i] + separator; } return result; }

Puteți trece orice număr de argumente acestei funcție și concatenează fiecare argument într-un șir „listă”:

// returnează „roșu, portocaliu, albastru”, myConcat (",", „roșu”, „orange”, „albastru”); // returnează „elefant; girafă; leu; ghepard;” myConcat (“;”, „elefant”, „girafă”, „leu”, „ghepard”); // returneaza "salvie. busuioc. oregano. piper. patrunjel." myConcat ("".", "salvie", "busuioc", "oregano", "piper", "patrunjel");

Notă: Variabila cu argumente este „asemănătoare matricei”, dar nu o matrice. Este asemănător unei matrice prin faptul că are un index numerotat și o proprietate de lungime. Cu toate acestea, nu posedă toate metodele de manipulare a matricei.

Doi factori au influențat introducerea funcțiilor săgeată: funcții mai scurte și neobligatoriu ale acestora.

Funcții mai scurte

În unele modele funcționale, funcțiile mai scurte sunt binevenite. Comparaţie:

Var a = ["Hidrogen", "Heliu", "Litiu", "Beriliu"]; var a2 = a.map (funcție (e) (return s.length;)); console.log (a2); // logs var a3 = a.map (s => s.length); console.log (a3); // jurnalele

Nu separă asta

Până la funcțiile săgeată, fiecare funcție nouă își definea propria valoare (un obiect nou în cazul unui constructor, nedefinit în apelurile de funcții, obiectul de bază dacă funcția este numită ca „metodă obiect”, etc.). Acest lucru sa dovedit a fi mai puțin decât ideal cu un stil de programare orientat pe obiecte.

Funcție Person () (// Constructorul Person () definește `this` ca sine.this.age = 0; setInterval (funcția growUp () (// În modul nestrict, funcția growUp () definește` this` // ca obiectul global, care este diferit de `this` // definit de Person () constructor.this.age ++;), 1000);) var p = new Person ();

În ECMAScript 3/5, această problemă a fost rezolvată prin atribuirea valorii din aceasta unei variabile care ar putea fi închisă.

Funcție Persoană () (var self = this; // Unii aleg `that` în loc de`self`. // Alegeți unul și fiți consistent.self.age = 0; setInterval (funcția growUp () (// Callback-ul se referă la variabila `self` a cărei // valoarea este obiectul așteptat.self.age ++;), 1000);)

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

Var add = functie (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 nume. În al doilea rând, este atribuită unei variabile, dar nu doar atribuită, dar corpul ei dispare imediat. Personal, pentru mine, care am scris anterior în limbi precum VB, C++, o astfel de declarație a provocat nedumerire și neînțelegere a modului în care funcționează și de ce să o scriu așa.

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

Funcția add (arg1, arg2) (var sum = arg1 + arg2; return sum;) var rezultat = add (5, 3); // rezultatul este acum 8

Și aici ajungem la particularitățile 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? Poti. Deci, dacă ne imaginăm că o funcție este o valoare obișnuită, deși o structură foarte complexă, atunci primul mod de a o declara nu mai pare ceva incredibil.

Următorul fapt interesant este o continuare logică a primului. După ce punem datele într-o variabilă, putem transfera datele într-o altă variabilă prin numele acestei variabile:

Var a = 5; var b = a; alerta (b); // va tipări 5

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

Var add = funcție (arg1, arg2) (var sum = arg1 + arg2; returnare sumă;) var calcSum = add; alertă (calcSum (5, 6)); // imprimă 11

Începi deja să ghicești? Deoarece o funcție este ca o variabilă, o putem „multiplica” prin intermediul unei atribuiri obișnuite în alte variabile, transformându-le și în funcții. Acum calcSum poate adăuga și două numere. Totuși codul

Var calcSum = aduna (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ă trebuie să executăm funcția, nu să o atribuim).

Dacă trebuie să apelați o funcție în sine, atunci aceasta se face după cum urmează:

Var calcFact = function fact (val) (daca (val == 1)? Val: val * fact (val - 1); // calculul factorial folosind recursiunea) alert (calcFact (4)); // imprimă 24

Aici, prin atribuirea unei funcții unei variabile, i-am dat numele faptului. Cu toate acestea, acest nume va fi disponibil numai în interiorul funcției în sine și nicăieri altundeva. Motivele pentru aceasta se află în principiul interpretului și depășesc domeniul de aplicare al lecției.

S-ar putea să vă întrebați: "Hmm, o oportunitate interesantă! Dar care este avantajul acestei metode? Există situații în care nu se poate face fără ea sau este cel puțin mai convenabil decât un anunț obișnuit?" Nu mă voi angaja să argumentez că există situații în care nu se poate renunța la o astfel de abordare, dar pot da un exemplu în care reduce cantitatea de cod. Să presupunem că trebuie să salutați o persoană în funcție de momentul zilei:

Var date = 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 „calea clasică”, atunci ar trebui să scriem trei funcții separate și apoi să le apelăm într-o condiție de verificare a timpului:

Funcția goodMorning () (alertă ("Bună dimineața!");) Funcția goodAfternoon () (alertă ("Bună ziua!");) Funcția 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 având în vedere că am folosit o formă scurtă de notație pentru operatorul condiționat. 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 folosite, cel mai probabil, o singură dată, nu este o idee bună. În plus, suntem obligați să dăm fiecărei funcții 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ă”, atunci 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.

V-am spus despre o caracteristică interesantă a funcțiilor JS și am dat exemple. Deci ai văzut asta moduri de a apela funcții în Javascript nu se limitează la o singură specie. Chiar dacă nu poți găsi imediat aplicație pentru aceste oportunități în proiectele tale, cel puțin vei ști că există astfel de oportunități. Și când vine norocul cu adevărat, puteți reduce cantitatea de cod și puteți evita confuziile și erorile inutile!

Acest articol descrie funcții la nivel de limbaj Javascript: creare, parametri, trucuri, închideri și multe altele.

Crearea de funcții

Există 3 moduri de a crea o funcție. Principala diferență ca urmare a muncii lor este că funcția numită este vizibilă peste tot, iar cea anonimă este vizibilă numai după declarație:

Funcții – obiecte

În javascript, funcțiile sunt obiecte cu drepturi depline ale clasei Function încorporate. De aceea pot fi atribuite variabilelor, trecute și, bineînțeles, au proprietăți:

Funcția f () (...) f.test = 6 ... alertă (f.test) // 6

Proprietățile funcției sunt, de asemenea, disponibile în interiorul funcției, astfel încât acestea pot fi utilizate ca variabile statice.

De exemplu,

Funcție func () (var funcObj = arguments.callee funcObj.test ++ alert (funcObj.test)) func.test = 1 func () func ()

La început, fiecare funcție creează o variabilă argumente în ea însăși și atribuie arguments.callee o referință la sine. Deci arguments.callee.test este o proprietate a func.test, adică testul variabilei statice.

În exemplu, atribuirea nu a putut fi făcută:

Var test = arguments.callee.test test ++

deoarece în acest caz operația ++ ar fi funcționat pe testul variabilei locale, și nu pe proprietatea de testare a obiectului funcție.

Obiectul arguments conține, de asemenea, toate argumentele și poate fi convertit într-o matrice (deși nu este), vezi mai jos în secțiunea despre parametri.

Domenii de aplicare

Fiecare funcție, sau mai degrabă fiecare lansare a unei funcții, își stabilește propriul domeniu de aplicare individual.

Variabilele pot fi declarate oriunde. Cuvântul cheie var setează o variabilă în domeniul curent. Dacă o uitați, atunci variabila va merge la obiectul fereastră globală. Sunt posibile intersecții neașteptate cu alte variabile ale ferestrei, conflicte și erori.

Spre deosebire de un număr de limbi, blocurile nu definesc un domeniu separat. Nu are nicio diferență dacă o variabilă este definită în interiorul blocului sau în afara acestuia. Deci, aceste două fragmente sunt perfect echivalente:

O variabilă specificată prin var este vizibilă peste tot în domeniul de aplicare, chiar înainte de instrucțiunea var. De exemplu, să facem o funcție care va schimba variabila, var pentru care se află mai jos.

De exemplu:

Funcția a () (z = 5 // schimbă z local .. // .. deoarece z este declarat prin var var z) // testează șterge z // șterge za globală () în caz de alertă (window.z) // => nedefinit deoarece z a fost modificat local

Parametrii funcției

Funcțiile pot fi executate cu orice număr de parametri.

Dacă funcției sunt trecuți mai puțini parametri decât există în definiție, atunci cei lipsă sunt considerați nedefiniți.

Următoarea funcție returnează timpul necesar pentru a parcurge distanța cu o viteză uniformă.

La prima lansare, funcția funcționează cu argumentele distanță = 10, viteză = nedefinit. De obicei, această situație, dacă este acceptată de funcție, oferă o valoare implicită:

// dacă viteza este o valoare falsă (nedefinită, 0, falsă ...) - înlocuiți 10 viteză = viteza || zece

Operator || în javascript nu returnează true / false, ci valoarea în sine (prima, care este turnată la adevărat).

Prin urmare, este folosit pentru a seta valorile implicite. În apelul nostru, viteza va fi nedefinită || 10 = 10.

Prin urmare, rezultatul va fi 10/10 = 1.

A doua lansare este standard.

A treia rulare oferă mai multe argumente suplimentare. Funcția nu prevede lucrul cu argumente suplimentare, așa că sunt pur și simplu ignorate.

Ei bine, în acest din urmă caz, nu există deloc argumente, deci distanță = nedefinită, iar rezultatul împărțirii este nedefinit / 10 = NaN (Nu-A-Număr, a apărut o eroare).

Lucrul cu un număr nedefinit de parametri

Chiar înainte de a intra în corpul funcției, este creat automat un obiect argumente care conține

  1. Apelați argumente începând de la zero
  2. Lungimea în proprietatea lungimii
  3. O referință la funcția însăși în proprietatea apelat

De exemplu,

Funcția func () (pentru (var i = 0; i

Proprietatea arguments este ca o matrice prin faptul că are o lungime și indici numerici. De fapt, argumentele nu aparțin clasei Array și nu conține metodele acesteia, cum ar fi push, pop și altele.

Dacă tot doriți să utilizați aceste metode, de exemplu, pentru a apela o altă funcție cu aceleași argumente, dar pe lângă prima, puteți crea o matrice reală din argumente:

Var args = Array.prototype.slice.call (argumente) // .. acum args este o matrice reală de argumente .. args.shift () ...

Puteți apela o funcție pe o matrice de argumente folosind aplica:

Var func = funcția (a, b) (alertă (a + b)) var arr = func.aply (null, arr) // => alertă (3)

Un exemplu de transmitere a unei funcții prin referință

O funcție poate fi transmisă cu ușurință ca argument unei alte funcții.

De exemplu, map preia funcția func, o aplică fiecărui element din matricea arr și returnează matricea rezultată:

Var map = funcție (func, arr) (var rezultat = for (var i = 0; i

Exemplu de utilizare:

Hartă (a alerga,) // =

Sau puteți crea o funcție anonimă direct în apelul la hartă:

// funcția anonimă triplează harta numerelor (funcția (a) (întoarce a * 3),) // =

Îmbinarea parametrilor într-un obiect

Există funcții ale căror argumente variază foarte mult.

De exemplu:

// puteți specifica doar o parte din argumente // nespecificate - sunt calculate sau luate implicit funcția resize (toWidth, toHeight, saveProportions, animate) (// valorile implicite saveProportions = saveProportions || true animate = animate | | adevărat toHeight = toHeight | | ...)

Un apel cu parametri opționali trebuie făcut astfel:

Redimensionați (100, nul, nul, adevărat)

Pentru a evita valorile nule inutile și pentru a face codul mai lizibil, utilizați ceva de genul „argumente ale cuvintelor cheie” care există în Python și Ruby. Pentru aceasta, mulți parametri sunt împachetati într-un singur obiect:

Redimensionarea funcției (setup) (// valori implicite var saveProportions = setup.saveProportions || true var animate = setup.animate || true var toHeight = setup.toHeight || ...)

Apelul este acum mult mai ușor:

Var setup = (toWidth: 100, animate: true) redimensionare (setup) // sau redimensionare ((toWidth: 100, animate: true))

Deci - mult mai clar. Și dacă există mai mult de 5 parametri, atunci în general - singurul mod normal.

În plus, este mai convenabil să faci o secvență de apeluri cu un obiect precum:

Var setup = (toWidth: 100, animate: true, saveProportions: false) resize (setup) setup.toWidth = 200 resize (setup)

Top articole similare