--- title: Funzioni slug: Web/JavaScript/Reference/Functions translation_of: Web/JavaScript/Reference/Functions original_slug: Web/JavaScript/Reference/Functions_and_function_scope ---
Parlando in termini generici, una funzione è un "sottopogramma" che può essere chiamato da un codice esterno (o interno nel caso di ricorsione) alla funzione stessa. Come il programma stesso, una funzione è composta da una sequenza di istruzioni chiamata corpo della funzione. Ad una funzione possono essere passati valori, e la funzione restituisce un valore.
In JavaScript, le funzioni sono oggetti di prima classe, perchè sono dotate di proprietà e di metodi, proprio come qualsiasi altro oggetto. Ciò che le distingue dagli altri oggetti è la possibilità di essere chiamate ( invocate ). Le funzioni sono oggetti di tipo Function
.
Per maggiori esempi e spiegazioni, vedere anche JavaScript la guida sulle funzioni.
Ogni funzione in JavaScript è un oggetto di tipo Function
. Vedi la pagina Function
for informazioni su proprietà e metodi dell'oggetto Function
.
Le funzioni non sono come le procedure. Una funzione restituisce sempre un valore, mentre una procedura può anche non restituire alcun valore.
Per restituire un valore specifico differente da quello di default, una fuzione deve avere un istruzione return
che specifica il valore di ritorno. Una funzione senza un istruzione di ritorno restituirà il valore di default. Nel caso di un costruttore invocato con la parola chiave new
, il valore di default è il valore del suo parametro this
. Per tutte le altre funzioni, il valore di ritorno di default è undefined
.
I parametri di una chiamata di funzione sono gli argomenti della funzione. Gli argomenti sono passati alla funzione per valore. Se la funzione cambia il valore di un argomento, questo cambiamento non si riflette globalmente o nella funzione chiamante. Sebbene anche i riferimenti a oggetti siano valori, essi sono speciali: se una funzione cambia le proprietà di un oggetto a cui riferisce, quel cambiamento è visibile anche al di fuori della funzione, come dimostrato nel seguente esempio:
/* Dichiarazione della funzione 'myFunc' */ function myFunc(theObject) { theObject.brand = "Toyota"; } /* * Dichiarazione della variabile 'mycar'; * creazione e inizializzazione di un nuovo Object; * associazione alla riferimento 'mycar' */ var mycar = { brand: "Honda", model: "Accord", year: 1998 }; /* Logs 'Honda' */ console.log(mycar.brand); /* Passaggio del riferimento dell'oggetto alla funzione */ myFunc(mycar); /* * Logs 'Toyota' come il valore della proprietà 'brand' * dell'oggetto, come è stato cambiato dalla funzione. */ console.log(mycar.brand);
NB: l'oggetto console non è un oggetto standard. Non usatelo in un sito web, poichè potrebbe non funzionare correttamente. Per verificare il funzionamento dell'esempio precedente, usate, piuttosto:
window.alert(mycar.brand);
La parola chiave this
non fa riferimento alla funzione attualmente in esecuzione, per questo motivo si deve far riferimento ad oggetti Function
per nome, anche quando all'interno del corpo della funzione stessa.
Ci sono diversi modi per definire le funzioni:
function
)C'è una speciale sintassi per la dichiarazione di funzioni (per dettagli guarda function statement):
function name([param[, param[, ... param]]]) { statements }
name
param
statements
function
)Una espressione di funzione è simile ed ha la stessa sintassi della dichiarazione di funzione (per dettagli guarda function expression):
function [name]([param] [, param] [..., param]) { statements }
name
param
statements
function*
)Note: Le funzioni generatrici sono un tecnologia sperimentale, parte della proposta di specifica ECMAScript 6, e non sono ancora ampiamente supportate dai browsers.
C'è una sintassi speciale per le funzioni generatrici (per dettagli vedi function* statement
):
function* name([param[, param[, ... param]]]) { statements }
name
param
statements
function*
)Note: Le funzioni generatrici sono una tecnologia sperimentale, parte della proposta di specifica ECMAScript 6, e non sono ancora ampiamente supportamente dai browsers.
Una espressione di funzione generatrice è similare ed ha la stessa sintassi di una dichiarazione di funzione generatrice (per dettagli vedi function* expression
):
function* [name]([param] [, param] [..., param]) { statements }
name
param
statements
Note: L'espressione di funzione a freccia sono una tecnologia sperimentare, parte della proposta di specifica ECMAScript 6, e non sono ancora ampiamente supportate dai browsers.
Un' espressione di funzione a freccia ha una sintassi ridotta e lessicalmnete associa il proprio valore this (per dettagli vedere arrow functions ):
([param] [, param]) => { statements } param => expression
param
()
. Le parentesi non sono richieste nel caso in cui ci sia solo un parametro (come foo => 1
).statements or expression
Function
Nota: l'utilizzo del costruttore Function
per creare funzioni non è raccomandato, poichè richiede che il corpo della funzione sia scritto come stringa, fatto che può comportare una mancata ottimizzazione da parte di alcuni motori javascript e causare altri problemi.
Come tutti gli altri oggetti, un oggetto Function
può essere creato utilizzando l'operatore new
:
new Function (arg1, arg2, ... argN, functionBody)
arg1, arg2, ... argN
x
", "theValue
", oppure "a,b
".functionBody
Invocare il costruttore Function
come funzione ( senza utilizzare l'operatore new
) ha lo stesso effetto di quando lo si invoca come costruttore.
GeneratorFunction
Nota: le espressioni di funzione a freccia ( arrow function expression ) sono una tecnologia sperimentale, parte della proposta ECMAScript 6, e non sono ancora completamente supportate dai browser.
Nota: il costruttore GeneratorFunction
non è un oggetto globale, ma può essere ottenuto dall'istanza della funzione generatrice ( vedi GeneratorFunction
per maggiori dettagli ).
Nota: l'utilizzo del costruttore GeneratorFunction
per creare funzioni non è raccomandato, poichè richiede che il corpo della funzione sia scritto come stringa, fatto che può comportare una mancata ottimizzazione da parte di alcuni motori javascript e causare altri problemi.
Come tutti gli altri oggetti, un oggetto GeneratorFunction
può essere creato utilizzando l'operatore new
:
new GeneratorFunction (arg1, arg2, ... argN, functionBody)
arg1, arg2, ... argN
x
", "theValue
", oppure "a,b
".functionBody
Invocare il costruttore Function
come funzione ( senza utilizzare l'operatore new
) ha lo stesso effetto di quando lo si invoca come costruttore.
Nota: i parametri di default ed i parametri rest sono tecnologie sperimentali, parte della proposta ECMAScript 6, e non sono ancora completamente supportati dai browser.
La sintassi per definire i valori di default dei parametri di una funzione permette di inizializzare i parametri formali con valori di default, sempre che non venga passato il valore undefined
oppure non venga passato alcun valore. Per maggiori dettagli, vedi default parameters.
La sintassi per i parametri rest permette di rappresentare un indefinito numero di argomenti come un array. Per maggiori dettagli, vedi rest parameters.
arguments
È possibile riferirsi agli argomenti di una funzione, all'interno della funzione, utilizzando l'oggetto arguments
. Vedi arguments.
arguments
: un oggetto, strutturato come un array, contenente gli argomenti passati alla funzione in esecuzione.arguments.callee
{{Deprecated_inline}}: la funzione in esecuzione.arguments.caller
{{Obsolete_inline}} : la funzione che ha invocato la funzione in esecuzione.arguments.length
: il numero degli argomenti passati alla funzione.È possibile definire metodi getter ( accessor method: metodi per l'accesso al valore di una variabile privata ) e metodi setter ( mutator method: metodi per la modifica del valore di una variabile privata ) per qulasiasi oggetto standard built-in o per qualsiasi oggetto definito dall'utente che supporti l'aggiunta di nuove proprietà. La sintassi da usare per la definizione di metodi getter e setter utilizza la sintassi per la definizione di valori letterali.
Lega ( bind ) una proprietà di un oggetto ad una funzione, che verrà invocata ogni volta in cui si cercherà di leggere il valore di quella proprietà.
Nota: le definizioni dei metodi sono tecnologie sperimentali, parte della proposta ECMAScript 6, e non sono ancora completamente supportate dai browser.
A partire da ECMAScript 6, è possibile definire propri metodi usando una sintassi più breve, simile alla sintassi usata per i metodi getter e setter. Vedi method definitions per maggiori informazioni.
var obj = { foo() {}, bar() {} };
Il costruttore
Function
vs. la dichiarazione di funzione vs. l'espressione di funzioneCompara i seguenti esempi:
Una funzione definita con la dichiarazione di funzione:
function multiply(x, y) { return x * y; }
Una espressione di funzione di una funzione anonima ( senza nome ), assegnata alla variabile multiply:
var multiply = function(x, y) { return x * y; };
Una espressione di funzione di una funzione chiamata func_name
, assegnata alla variabile multiply:
var multiply = function func_name(x, y) { return x * y; };
Tutti e tre gli esempi fanno più o meno la stessa cosa, con qualche piccola differenza:
C'è una differenza tra il nome di una funzione e la variabile alla quale la funzione viene assegnata. Il nome di una funzione non può essere modificato, mentre la variabile alla quale viene assegnata la funzione può essere riassegnata. Il nome di una funzione può essere utilizzato solo all'interno del corpo della funzione. Tentare di utilizzarlo al di fuori del corpo della funzione genererà un errore ( oppure restituirà undefined
se il nome della funzione era stato precedentemente dichiarato con un'istruzione var
). Per esempio:
var y = function x() {}; alert(x); // throws an error
Il nome di una funzione appare anche quando la funzione viene serializzata usando il metodo toString applicato alla funzione.
Dall'altro lato, la variabile alla quale viene assegnata la funzione è limitata solo dal suo scope, la cui inclusione è garantita al momento della dichiarazione di funzione.
Come si può vedere dal quarto esempio, il nome della funzione può essere diverso dal nome della variabile alla quale la funzione viene assegnata. I due nomi non hanno alcuna relazione tra loro. Una dichiarazione di funzione crea anche una variabile con lo stesso nome della funzione. Quindi, diversamente dalle funzioni definite attraverso un'espressione di funzione, le funzioni definite attraverso una dichiarazione di funzione offrono la possibilità di accedere ad esse attraverso il loro nome, almeno all'interno dello scope in cui erano state definite.
Una funzione definita con il costruttore 'new Function'
non possiede un nome. Tuttavia, nel motore JavaScript SpiderMonkey, la forma serializzata della funzione mostra il nome "anonymous". Per esempio, il codice alert(new Function())
restituisce:
function anonymous() { }
Poichè la funzione, in realtà, non ha un nome, anonymous
non è una variabile alla quale si potrà accedere, all'interno della funzione. Per esempio, il seguente codice restituirebbe un errore:
var foo = new Function("alert(anonymous);"); foo();
Diversamente da quanto accade con le funzioni definite con espressioni di funzione o con il costruttore Function
, una funzione definita con una dichiarazione di funzione può essere usata prima della dichiarazione di funzione stessa. Per esempio:
foo(); // alerts FOO! function foo() { alert('FOO!'); }
Una funzione definita da un'espressione di funzione eredita lo scope corrente. Vale a dire, la funzione forma una chiusura. Dall'altro lato, una funzione definita dal costruttore Function
non eredita alcuno scope, se non quello globale ( che eredita qualsiasi funzione ).
Le funzioni definite con espressioni di funzione e dichiarazioni di funzione vengono analizzate ( parsed ) solo una volta, mentre quelle definite con il costruttore Function
no. Vale a dire, la stringa testuale del corpo della funzione passata al costruttore Function
deve essere analizzata ( parsed ) ogni volta in cui viene invocato il costruttore. Sebbene un'espressione di funzione crei ogni volta una chiusura, il corpo della funzione non viene rianalizzato ( reparsed ), così le espressioni di funzione sono ancora più veloci del "new Function(...)
". Quindi, il costruttore Function
dovrebbe, generalmente, essere evitato dove possibile.
Occorre tenere presente, tuttavia, che le espressioni di funzione e le dichiarazioni di funzione annidate in una funzione generata dall'analisi ( parsing ) di una stringa del costruttore Function non vengono analizzate (
parsed ) continuamente. Per esempio:
var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))(); foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.
Una dichiarazione di funzione è molto facilmente ( e spesso, anche non intenzionalmente ) convertita in un'espressione di funzione. Una dichiarazione di funzione cessa di essere tale quando:
var x = 0; // source element if (x == 0) { // source element x = 10; // not a source element function boo() {} // not a source element } function foo() { // source element var y = 20; // source element function bar() {} // source element while (y == 10) { // source element function blah() {} // not a source element y++; // not a source element } }
// function declaration function foo() {} // function expression (function bar() {}) // function expression x = function hello() {} if (x) { // function expression function world() {} } // function declaration function a() { // function declaration function b() {} if (0) { // function expression function c() {} } }
Le funzioni possono essere definite in modo condizionato, utilizzando sia le istruzioni di funzione ( un'estensione prevista nello standard ECMA-262 Edition 3 ), sia il costruttore Function
. Da notare, però, che le istruzioni di funzione non sono più accettate in ES5 strict mode. Inoltre, questa funzionalità non funziona bene attraverso più browser, quindi sarebbe meglio non farci affidamento.
Nello script seguente, la funzione zero
non verrà mai definita e non potrà mai essere invocata, visto che 'if (0)
' restituisce sempre false:
if (0) { function zero() { document.writeln("This is zero."); } }
Se la condizione diventasse 'if (1)
', la funzione zero
verrebbe definita.
Nota: sebbene questo tipo di funzione sembri una dichiarazione di funzione, in realtà siamo di fronte ad una espressione ( o statement, o istruzione ), poichè la dichiarazione è annidata all'interno di un'altra istruzione. Vedi le differenze tra dichiarazioni di funzione ed espressioni di funzione.
Nota: alcuni motori JavaScript, eslcuso SpiderMonkey, trattano, non correttamente, qualsiasi espressione di funzione in modo da assegnare loro un nome, al momento della definizione. Questo comporterebbe che la funzione zero
sarebbe comunque definita, anche nell'eventualità che la condizione if restituisse
sempre false. Un modo più sicuro per definire le funzioni in modo condizionato è di definirle come funzioni anonime ed assegnarle, poi, ad una variabile:
if (0) { var zero = function() { document.writeln("This is zero."); } }
La seguente funzione restituisce ( return ) una stringa contenente la rappresentazione formattata di un numero, completato ( padded ) con degli zero iniziali.
// This function returns a string padded with leading zeros function padZeros(num, totalLen) { var numStr = num.toString(); // Initialize return value as string var numZeros = totalLen - numStr.length; // Calculate no. of zeros for (var i = 1; i <= numZeros; i++) { numStr = "0" + numStr; } return numStr; }
Queste istruzioni invocano la funzione padZeros.
var result; result = padZeros(42,4); // returns "0042" result = padZeros(42,2); // returns "42" result = padZeros(5,4); // returns "0005"
È possibile determinare se una funzione esiste, utilizzando l'operatore typeof
. Nell'esempio seguente, viene eseguito un test per determinare se l'oggetto window
ha una proprietà, che sia una funzione, chiamata noFunc
. Se così, la funzione verrà utilizzata; in caso contrario, verrà eseguita una qualsiasi altra azione.
if ('function' == typeof window.noFunc) { // use noFunc() } else { // do something else }
Da notare che nel test if
viene usato un riferimento a noFunc
— senza usare le parentesi "()" dopo il nome della funzione: in questo modo, la funzione non viene invocata.
Specification | Status | Comment |
---|---|---|
ECMAScript 1st Edition. | Standard | Initial definition. Implemented in JavaScript 1.0 |
{{SpecName('ES5.1', '#sec-13', 'Function Definition')}} | {{Spec2('ES5.1')}} | |
{{SpecName('ES6', '#sec-function-definitions', 'Function definitions')}} | {{Spec2('ES6')}} | New: Arrow functions, Generator functions, default parameters, rest parameters |
{{SpecName('ES6', '#', 'function*')}} | {{Spec2('ES6')}} | Initial definition. |
{{SpecName('ES6', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}} | {{Spec2('ES6')}} | Initial definition. |
{{CompatibilityTable}}
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} |
Generator function | 39 | {{CompatGeckoDesktop("26.0")}} | {{CompatUnknown}} | 26 | {{CompatUnknown}} |
Arrow function | {{CompatNo}} | {{CompatGeckoDesktop("22.0")}} | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} | {{CompatVersionUnknown}} |
Generator function | {{CompatUnknown}} | 39 | {{CompatGeckoMobile("26.0")}} | {{CompatUnknown}} | 26 | {{CompatUnknown}} |
Arrow function | {{CompatNo}} | {{CompatNo}} | {{CompatGeckoMobile("22.0")}} | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |