Apelarea unei funcții în javascript. Cinci moduri de a apela o funcție

Funcții

O 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 conceptul de 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 calcula o valoare returnată, care este valoarea expresiei de apelare a funcției. Pe lângă argumente, atunci când orice funcție este apelată, i se mai trece o valoare care definește contextul apelului - valoarea din cuvântul cheie this.

Funcțiile din JavaScript sunt obiecte și pot fi utilizate în moduri diferite. De exemplu, funcțiile pot fi atribuite variabilelor și transmise altor funcții. Deoarece funcțiile sunt obiecte, puteți atribui valori proprietăților lor și chiar le puteți apela metode.

JavaScript permite definițiile de funcții să fie 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

O definiție a funcției începe cu cuvântul cheie function, urmat de următoarele componente:

Un identificator care specifică 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. În expresiile de definire a funcției, numele poate fi absent: 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 bretele cu zero sau mai multe instrucțiuni JavaScript în interior

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 sub formă de instrucțiuni și expresii. Rețineți că definițiile funcției ca expresii sunt utile numai dacă fac parte din expresii mai mari, cum ar fi o atribuire sau un apel de funcție, care fac ceva cu funcția nou declarată:

// Tipărește numele și valorile tuturor proprietăților funcției obiect obj printprops(obj) ( for(var p în obj) console.log(p + ": " + obj[p] + "\n"); ) // Calculeaza distanta dintre punctele (x1,y1) si (x2,y2) function distance(x1, y1, x2, y2) ( var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx) *dx + dy*dy ) // Funcție recursivă (denumită în sine) care calculează funcția factorială factorial(x) ( if (x);

Rețineți că în expresiile de definire a funcției, numele funcției poate să nu fie prezent. Instrucțiunea de declarare a funcției declară de fapt o variabilă și îi atribuie un obiect funcție.

O expresie de definiție a funcției, pe de altă parte, nu declară o variabilă. Cu toate acestea, în expresiile de definiție este posibil să se specifice numele funcției, ca în funcția factorială de mai sus, care poate fi necesar în corpul funcției pentru a se autodenomina. Dacă o expresie de definiție a funcției include un nume, acel nume se va referi la un obiect funcție 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, făcând 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 termină funcția și returnează valoarea expresiei acesteia (dacă este specificată) programului apelant. Dacă nu există nicio 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ă la 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 ei este de a tipări numele proprietăților unui obiect. Nu trebuie să returneze nicio valoare, deci nu există nicio instrucțiune return î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 de program care formează corpul unei funcții 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 cu o listă separată de virgulă de zero sau mai multe expresii argument în interior.

Dacă o expresie de apel de funcție este o expresie de apel de proprietate - dacă funcția este o proprietate de obiect sau un element de matrice (adică o metodă) - atunci expresia de apel este o expresie de apel de metodă. Următorul fragment arată câteva exemple de expresii de apel de funcții comune:

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 o funcție 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 funcției, 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ă o funcție revine după ce interpretul a ajuns la sfârșit, este returnat undefined. 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.

O 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, atunci puteți defini o metodă a obiectului 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 o metodă la obiectul obj obj.method = func; // Acum puteți apela această metodă var result = obj.method(4, 5);

Cel mai adesea, la apelarea metodelor, se folosește forma de acces la proprietate folosind operatorul punct, dar puteți utiliza și forma de acces la proprietate folosind paranteze drepte. De exemplu, ambele dintre următoarele expresii sunt expresii de apel de metodă:

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

Argumentele și valoarea returnată a unui apel de metodă sunt procesate exact în același mod ca un apel de funcție normal. Cu toate acestea, un apel de metodă are o diferență importantă: contextul apelului. O expresie de acces la proprietate constă din două părți: un obiect (în acest caz, obj) și numele proprietății (metodă). În astfel de expresii de apel de metodă, obj devine contextul de apelare, iar corpul funcției poate face referire la acel obiect folosind cuvântul cheie this. De exemplu:

Var obj = ( x: 0, y: 0, // Adăugați metoda: function(a, b) ( this.x = a; this.y = b; ), // O altă metodă sumă: function() ( return this .x + this.y ) ); // Apelarea metodelor obj.add(15, 4); console.log(obj.sum()); // 19

Metodele și cuvântul cheie this 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ă anumite operații asupra unui obiect, iar sintaxa apelului de metodă reflectă în mod clar faptul că funcția operează asupra obiectului.

Vă rugăm să rețineți: acesta este un cuvânt cheie, nu o variabilă sau un nume de proprietate. Sintaxa JavaScript nu permite acestui element să i se atribuie o valoare.

Argumente și parametrii funcției

În JavaScript, definițiile funcțiilor nu specifică tipurile de parametri, iar apelurile de funcții nu efectuează nicio verificare a tipului asupra valorilor argumentelor transmise. De fapt, JavaScript nici măcar nu verifică numărul de argumente atunci când apelează funcții. Subsecțiunile de mai jos descriu ce se întâmplă dacă 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 setate la nedefinit. Este adesea convenabil să scrieți funcții, astfel încât unele dintre argumente să fie opționale și să poată fi omise la apelarea funcției. În acest caz, este de dorit să se ofere posibilitatea de a atribui parametrilor care pot fi omisi valori implicite rezonabile. De exemplu:

// Adăugați nume enumerabile 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 a new for( var proprietate în obj) arr.push(property 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ățile 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ă completeze 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 valoarea nedefinită în primul argument. De asemenea, rețineț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 nu poate accesa direct valorile nenumite. Soluția la această problemă este oferită de obiectul Arguments. În corpul funcției, identificatorul de argumente se referă la obiectul Arguments prezent în apel. Obiectul Arguments este un obiect asemănător matricei care permite ca valorile transmise unei funcții să fie preluate prin numere, mai degrabă decât prin nume.

Să presupunem că a fost definită o funcție func care necesită un argument x. Dacă apelați această funcție cu două argumente, 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 specifică numărul de elemente pe care le conține. Adică, în corpul unei funcții numită func cu două argumente, arguments.length are valoarea 2.

Obiectul Argumente poate fi folosit pentru o 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, ceva ce JavaScript nu va face pentru dvs.:

Funcția func(x, y, z) ( // Verifică mai întâi dacă este transmis numărul corect de argumente dacă (arguments.length != 3) ( throw new Error("Func numită cu argumente " + arguments.length + " și necesar 3."); ) // Și acum codul funcției în sine... )

Rețineți că adesea nu este necesar să verificați numărul de argumente, ca în acest exemplu. Comportamentul implicit al interpretului JavaScript este bun pentru majoritatea cazurilor: argumentele lipsă sunt înlocuite cu valoarea nedefinită, 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 ia orice număr de argumente și returnează valoarea celui mai mare (funcția încorporată Math.max() 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 pentru (var i = 0; i m) m = arguments[i]; // Returnează cea mai mare valoare returnată 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 sunt numite 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 variadice nu trebuie să fie apelate cu o listă de argumente goală. Este perfect logic să folosiți obiectul arguments atunci când scrieți o funcție care așteaptă un număr fix de argumente numite necesare, urmat de un număr arbitrar de argumente opționale fără nume.

Nu uitați că arguments nu este de fapt o matrice - este un obiect Arguments. Fiecare obiect Arguments are elemente de matrice numerotate și o proprietate de lungime, dar nu este din punct de vedere tehnic o matrice. Este mai bine să ne gândim la el ca la un obiect care are unele proprietăți numerotate.

În plus față de elementele de matrice, obiectul Arguments definește proprietățile apelantului și apelantului. Încercarea de a schimba valorile acestor proprietăți în modul strict ECMAScript 5 este garantată să arunce 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ției

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 sunt de fapt un tip special de obiect în JavaScript. Și deoarece funcțiile sunt obiecte, ele au proprietăți și metode ca orice alte obiecte. 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 specifică 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 matrice de argumente de la o altă funcție. Acesta 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-au fost transmise atâtea argumente cât se așteaptă. Dacă valorile nu se potrivesc, se face o excepție. Funcția check() este urmată de o funcție de testare, func(), care demonstrează cum se utilizează funcția check():

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

proprietate prototip

Fiecare 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 într-un articol anterior.

metodele call() și apply().

Metodele call() și apply() vă permit să apelați o funcție indirect, ca și cum ar fi o metodă pe alt obiect. Primul argument pentru ambele metode call() și apply() este obiectul pe care este apelată funcția; acest argument specifică 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 call() sau apply():

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

Oricare mod de a-l apela este echivalent cu următorul fragment (presupunând că obj nu are o proprietate numită m):

Obj.m = func; // Faceți temporar funcția o metodă obj obj.m(); // Numiți-o fără argumente. deleteobj.m; // Eliminați metoda temporară.

În modul strict ECMAScript 5, primul argument al metodelor call() și apply() devine valoarea acestuia, chiar dacă este o valoare simplă, nulă sau nedefinită. În ECMAScript 3 și în modul lax, valorile null și undefined 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 de apelare 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 este capabilă să proceseze un număr arbitrar de argumente, metoda apply() poate fi folosită pentru a apela o astfel de funcție în contextul unui tablou de lungime arbitrară.

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

// Mai jos sunt două funcții care afișează proprietățile și // valorile proprietăților unui obiect arbitrar. Metoda // se afișează ca argument func function 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 apărea 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 lui func și îi treceți un obiect obj, va returna o nouă funcție. Apelarea noii funcție (ca o funcție obișnuită) va apela funcția originală func ca metodă pe obj. Orice argumente transmise noii funcție vor fi transmise funcției inițiale. De exemplu:

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

Acest tip 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 obiect obj // și îi transmite toate argumentele sale function bind(func, obj) ( if (func.bind) return func.bind(obj); // Folosește metoda bind dacă available else return function() ( // În caz contrar se leagă ca mai jos return func.apply(obj, arguments); )

Metoda bind() din ECMAScript 5 face mai mult decât să lege o funcție la un obiect. De asemenea, efectuează casting parțial: în plus față de această valoare, toate argumentele transmise metodei bind() după primul argument vor fi legate. Aplicarea parțială este o tehnică comună în programarea funcțională și uneori este numită curry.

Să începem cu faptul că limbajul JavaScript acceptă conceptul de OOP (programare orientată pe obiect). Acest concept este că există elemente precum obiectele și aceste obiecte au diverse proprietăți și metode (funcții) care vă permit să le manipulați.

O funcție este un singur bloc de cod care constă din una sau mai multe instrucțiuni. Are un nume propriu (unic) și poate accepta diverși parametri, în funcție de care poate efectua o anumită operație.

O metodă este, de asemenea, o funcție, dar aparține deja unei clase sau obiecte.

Pentru a apela o metodă, trebuie mai întâi să scrieți numele obiectului, apoi să scrieți numele metodei despărțit de un punct. Excepția de la această regulă este atunci când apelați metodele alert(), confirm() și prompt() ale obiectului fereastră. Ele pot fi apelate fără a specifica numele obiectului. Ne-am familiarizat deja cu aceste metode în acest articol.

De asemenea, în articolele anterioare ne-a fost introdus metoda de ieșire document.write(), care aparține obiectului document.

Deci, în programare există o oportunitate foarte importantă, și anume că vă puteți crea propriile funcții.

Sintaxa funcției arată astfel:


De exemplu, să creăm o funcție simplă care va adăuga textul transmis la un paragraf și îl va afișa. Și îl va face, de asemenea, îndrăzneț și italic.

Funcția writeText(text)( //Adăugați text în paragraf și afișați-l document.write("

„+text+”

"); ) //Apelați funcția creată writeText ("Bună ziua!");

Salvați documentul și deschideți-l în browser.


Cometariu! La declararea unei funcții trebuie să fie prezente acolade, indiferent de câți operatori sunt.

De ce sunt necesare funcții în programare?

Principalul avantaj al utilizării funcției este reducerea dimensiunii codului sursă a scriptului.

Să presupunem că trebuie să iterăm peste trei tablouri unidimensionale. După cum știm din acest articol: , matricea este iterată folosind o buclă. Fără funcție, codul pentru acest script va arăta astfel:

//declară trei tablouri var arr1 = ; var arr2 = ["b", 5, 9,2, "h", 8, 2]; var arr2 = ; pentru(var i = 0; i< arr1.length; i++){ document.write("

Elementul de matrice arr1, cu indexul " + i + " este egal cu: "+ arr1[i] +"

"); ) pentru (var i = 0; i< arr2.length; i++){ document.write("

Elementul de matrice arr2, cu indexul " + i + " este egal cu: "+ arr2[i] +"

"); ) pentru (var i = 0; i< arr3.length; i++){ document.write("

Elementul de matrice arr3, cu indexul " + i + " este egal cu: "+ arr3[i] +"

"); }

Deci, pentru a nu scrie propria buclă pentru fiecare matrice, este mai bine să folosiți o funcție în care trecem matricea, iar aceasta își va afișa toate elementele pe ecran. În acest fel, în primul rând, reducem dimensiunea codului și, în al doilea rând, scăpăm de repetarea codului.

Funcția printArr(arr)( for(var i = 0; i< arr.length; i++){ document.write("

Elementul de matrice cu indexul „ + i + ” este egal cu: „+ arr[i] +”

"); ) ) //declară trei tablouri var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; //Apelați funcția creată pentru a itera prin fiecare matrice printArr (arr1); printArr(arr2);

Parametrii funcției

O funcție poate lua orice număr de parametri, de la unu la infinit. Sau, poate fi complet fără parametri.

Să creăm o funcție fără parametri care imprimă pur și simplu fraza clasică „Hello world” pe ecran.

Funcția helloWorld())( document.write("Hello World"); ) //Apelați funcția fără parametri, helloWorld helloWorld();

Orice parametru de funcție poate avea propria sa valoare implicită. Aceasta înseamnă că dacă nu transmitem nicio valoare acestui parametru atunci când apelăm funcția, acesta va folosi valoarea implicită.

De exemplu, să creăm o funcție care adaugă două numere trecute. Dacă trecem doar un număr, atunci, implicit, al doilea număr va fi 4.

Funcția summa(număr1, număr2 = 4)( document.write("

Suma numerelor " + număr1 + " (Primul parametru) și " + numărul2 + " (Al doilea parametru) este egală cu: " + (numărul1 + numărul2) + "

"); ) //Apelați o funcție care, implicit, va scoate rezultatul adunării numărului trecut, cu numărul 4. summa(5); // Rezultat: 9 //Dacă furnizăm și al doilea parametru, funcția va afișa rezultatul adunării numerelor din ambii parametri .summa(5, 20) // Rezultat: 25;

De asemenea, este posibil ca în interiorul unei funcții să se poată apela o altă funcție existentă.

De exemplu, să apelăm prima funcție pe care am creat-o, writeText(), în cadrul funcției anterioare summa(). Vom transmite rezultatul adăugării de numere la funcția writeText(). În acest caz, codul pentru funcția summa() va arăta astfel:

Funcția summa(număr1, număr2 = 4)( scrieText(număr1 + număr2); ) //Apelați funcția summa summa(5); // Rezultat: 9 summa(5, 20); // Rezultat: 25

Funcții care returnează o anumită valoare

Până acum avem funcții scrise care afișează imediat rezultatul pe ecran.

Acum să învățăm cum să scriem o funcție care returnează un rezultat. Putem adăuga acest rezultat la o variabilă și putem lucra cu el în continuare.

Pentru a înțelege mai bine despre ce vorbim, să ne amintim metode precum prompt() și confirm(). Aceste metode returnează de fapt valoarea primită de la utilizator, mai degrabă decât să o afișeze.

De exemplu, să creăm propria noastră funcție care va returna ultimul element al matricei transmis ca parametru.

Funcția lastElement(arr)( //Return ultimul element al matricei transmise return arr; ) //Declară matricea var otherArr = ["iphone", "asus", 2000, 9.8, "twix"]; //Apelați funcția creată lastElement și transmiteți-i matricea creată ca parametru otherArr var lastEl = lastElement(otherArr); //Afișează ultimul element rezultat al matricei alert(lastEl);

Ca rezultat, vom obține cuvântul „twix”, deoarece acest cuvânt este ultimul element al matricei otherArr.

Metoda alert() nu returnează nimic. Adică, dacă încercăm să afișăm o variabilă al cărei tip conține rezultatul apelării metodei alert(), vom vedea valoarea undefined . Este același lucru cu încercarea de a afișa valoarea unei variabile goale.

De exemplu, să luăm rezultatul ultimului apel la alert() din exemplul anterior, să îl punem în variabila resAlert și să folosim funcția writeText pe care am creat-o pentru a încerca să tipărim rezultatul.

//Afișează ultimul element primit al matricei var resAlert = alert(lastEl); test var; scrieText(resAlert); // scrieText nedefinit(test); //nedefinit

După cum puteți vedea, în ambele cazuri am primit valoarea nedefinită.

Variabile globale și locale

Variabilele globale sunt acele variabile care sunt declarate în afara funcției. Adică, toate acele variabile care nu sunt declarate în interiorul funcției în sine sunt globale. Sunt vizibile (valide) pe tot parcursul documentului.

Variabilele locale sunt acele variabile care sunt declarate în cadrul funcției în sine. Și sunt valabile numai în cadrul unei anumite funcții. În afara acestuia, variabilele locale nu vor mai funcționa.

Variabilele locale și globale nu sunt legate între ele în niciun fel.


În exemplul din imagine, dacă am încerca să tipărim conținutul variabilei x, am primi un mesaj nedefinit deoarece am uitat să apelăm funcția other().

Prin urmare, pentru ca modificările făcute în interiorul funcției să funcționeze, este necesar să apelați această funcție.

Apelăm funcția other() și dacă acum încercăm să afișăm valoarea variabilei x, vom vedea ca rezultat numărul 4.

Pentru a accesa o variabilă globală din interiorul unei funcții, nu trebuie să faceți nimic, trebuie doar să o utilizați. Modificările aduse variabilelor globale vor fi vizibile în afara funcției.

Var x = 8; function increment() ( x++; ) //Apeleaza functia increment() increment(); alertă(x); //Rezultat: 9

Dacă nu dorim ca variabila globală să se modifice, trebuie să declarăm o variabilă locală (eventual cu același nume cu cea globală) și toate acțiunile vor fi efectuate asupra acesteia.

Var g = 100; funcția func())( var g = 14; g *= 2; // Este la fel ca g = g * 2 alert(g); // Rezultat: 28 ) // Apelați funcția. func(); alert(g);//Rezultat: 100

Asta e tot, dragi cititori, acum știți ce este o funcție, cum să vă creați propria funcție, cum să apelați o funcție și ce tipuri de funcții există. De asemenea, ați învățat ce sunt variabilele globale și locale.

După cum am scris la începutul articolului, funcțiile sunt elemente foarte importante, așa că ar trebui să le cunoașteți perfect.

Sarcini
  • Creați o funcție care ia două numere ca parametri și returnează rezultatul înmulțirii acestor numere.
  • Imprimați rezultatul.
  • 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 multi-paradigma ș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ștepta. 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(typeof window.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? Cititi 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 voi intra în detalii despre declararea tipurilor personalizate în JavaScript, dar cred că este necesar să vă reamintesc că nu există clase în JavaScript și orice tip personalizat 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ă valorile î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.

    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 text tip script), 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)); 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< 20"); }

    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.

    Rău Bun

    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.

    O 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 denumește pur și simplu funcția și specifică ce trebuie făcut atunci când funcția este apelată. Apelarea funcției realizează de fapt acțiunile specificate cu parametrii indicați. De exemplu, dacă definiți funcția pătrat, o 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 domeniu 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ția pătrat(n) ( returnează 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 square = function(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)); )

    Puteți calcula apoi 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 primește 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 apply(), poate fi folosită pentru a atinge acest obiectiv.

    Domeniul de aplicare al 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; ) multiply(); // 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 Recursie

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

  • numele funcției
  • 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 = function bar() ( // instrucțiunile merg aici );

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

  • bar()
  • arguments.callee()
  • foo()
  • 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 funcției(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(node) ( 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 funcției, 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 de tip stivă 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 square(x) ( return x * x; ) return square(a) + square(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) ( return x + y; ) return inside; ) fn_inside = outside(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) ( console.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:

  • B formează o închidere care include A, adică B poate accesa argumentele și variabilele lui A.
  • C formează o închidere care include B.
  • Deoarece închiderea lui 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 a 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 scopului. 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) ( return 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 parametrul x din interiorul lui și variabila x din exteriorul lui. Lanțul de acoperire aici este (interior, exterior, obiect global). Prin urmare, în interiorul „s x are prioritate față de exteriorul „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 interne 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 interne. 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 = function(name) ( // Funcția exterioară definește o variabilă numită "nume" var getName = function() ( return name; // Funcția interioară are acces la variabila "nume" a //funcției externe ) return getName // Returnează funcția internă, expunând-o astfel la sfera exterioară ) myPet = pet("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(name) ( var sex; return ( setName: function(newName) (nume = newName; ), getName: function() ( return name; ), getSex: function() ( return sex; ), setSex: function(newSex) ( if(typeof newSex === „șir” && (newSex.toLowerCase() === „bărbat” || newSex.toLowerCase() === „femeie”)) ( sex = newSex; ) ) ) ) var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("Oliver"); pet.setSex ("masculin"); 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 = (function() ( 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 exterior din nou.

    Var createPet = function(name) ( // Funcția exterioară definește o variabilă numită "nume". return ( setName: function(name) ( // 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 arguments . 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 oficial că acceptă. Acest lucru este adesea util dacă nu știți în avans 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; // repetă 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ții ș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 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ția Person() ( // Constructorul Person() definește `this` ca el însuși. this.age = 0; setInterval(function growUp() ( // În modul nestrict, funcția growUp() definește `this` // ca obiectul global, care este diferit de `this` // definit de constructorul Person() this.age++), 1000);

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

    Funcția Persoană() ( var self = this; // Unii aleg `that` în loc de `self`. // Alegeți unul și fiți consecvenți. self.age = 0; setInterval(function growUp() ( // callback-ul se referă la variabila `self` a carei // valoarea este obiectul asteptat self.age++), 1000);