Le funzioni con nome o le funzioni anonime sono preferite in JavaScript?

Possibile duplicato:
JavaScript: var functionName = function () {} vs function functionName () {}

Esistono due metodi possibili per estrarre una funzione in Javascript:

var foo = function() { ... } 

(questo è un po ‘forzato, un altro modello comune è:

 var foo = { baz: 43, doSomething:function() { ... } } 

)

contro

 function foo() { ... } 

C’è una ragione esplicita per preferire l’uno o l’altro?

Tutto si riduce alla preferenza per dove dichiari le tue funzioni; sollevamento.

Le dichiarazioni delle funzioni e le dichiarazioni delle variabili vengono sempre spostate (“issate”) invisibilmente nella parte superiore del loro ambito di contenimento dall’interprete JavaScript. Parametri di funzione e nomi definiti dalla lingua sono, ovviamente, già lì. Ciò significa che il codice come questo:

 function foo() { bar(); var x = 1; } 

è in realtà interpretato in questo modo:

 function foo() { var x; bar(); x = 1; } 

Si noti che la parte di assegnazione delle dichiarazioni non è stata sollevata. Solo il nome è issato. Questo non è il caso delle dichiarazioni di funzioni, dove verrà anche issato l’intero corpo della funzione.

 function test() { foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { // function expression assigned to local variable 'foo' alert("this won't run!"); } function bar() { // function declaration, given the name 'bar' alert("this will run!"); } } test(); 

In questo caso, solo la dichiarazione della funzione ha il suo corpo sollevato verso l’alto. Il nome ‘foo’ viene issato, ma il corpo viene lasciato indietro, da assegnare durante l’esecuzione.

Puoi dare nomi alle funzioni definite nelle espressioni di funzione, con la syntax come una dichiarazione di funzione. Questo non lo rende una dichiarazione di funzione, e il nome non è portato nel campo di applicazione, né il corpo è issato.

 foo(); // TypeError "foo is not a function" bar(); // valid baz(); // TypeError "baz is not a function" bin(); // ReferenceError "bin is not defined" var foo = function () {}; // anonymous function expression ('foo' gets hoisted) function bar() {}; // function declaration ('bar' and the function body get hoisted) var baz = function bin() {}; // named function expression (only 'baz' gets hoisted) foo(); // valid bar(); // valid baz(); // valid bin(); // ReferenceError "bin is not defined" 

Quindi, se la tua preferenza è quella di avere le funzioni di sollevamento verso l’alto usa una function declaration altrimenti usa l’ expression . Preferisco quest’ultimo dato che in genere realizzo i letterali degli oggetti con i metodi come function expressions .

Le function expressions nome possono essere utili quando vengono generati errori. La console ti dirà qual è la funzione invece di dichiarare la traccia anonymous stack .

Hai trovato un paio di cose diverse qui, ma proverò a rispondere per prima cosa alla tua domanda principale.

In generale….

function() { ... } è un’espressione di funzione . Sintatticamente questo è allo stesso livello di 2 o [4,5] . Questo rappresenta un valore . Così facendo var foo=function(){ ... } funzionerà come pianificato, ogni volta.

function foo() { ... } è una dichiarazione di funzione. Questo potrebbe sembrare lo stesso di var foo=function(){...} , ma c’è un piccolo avvertimento. Essendo una dichiarazione, funziona in modo simile al concetto di sollevamento variabile in JS (in pratica tutte le dichiarazioni delle variabili vengono eseguite prima che qualsiasi espressione venga valutata).

Un buon esempio è da qui :

 function test() { foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { // function expression assigned to local variable 'foo' alert("this won't run!"); } function bar() { // function declaration, given the name 'bar' alert("this will run!"); } } test(); 

Il sollevamento sostanzialmente variabile ha portato il valore in alto, quindi questo codice è equivalente ( in teoria ) a:

 function test() { var foo;//foo hoisted to top var bar=function(){//this as well alert("this will run!"); } foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { // function expression assigned to local variable 'foo' alert("this won't run!"); } } 

NB: Mi piacerebbe prendere questo punto per dire che gli interpreti JS hanno difficoltà a seguire la teoria, quindi non è consigliabile affidarsi a un comportamento un po ‘incerto. Qui troverai un buon esempio alla fine di una sezione in cui teoria e pratica finiscono per non funzionare (ci sono anche alcuni dettagli sull’argomento delle espressioni vs dichiarazioni).

Fatto divertente: il wrapping della function foo() {...} tra parentesi lo trasforma da una dichiarazione a un’espressione, che può portare a qualche strano codice come

 (function foo() { return 1; })();// 1 foo; //ReferenceError: foo is not defined 

Non farlo se non hai una ragione, per favore.


Riepilogo var foo=function(){ ... } è * sorta kinda * lo stesso di function foo(){ ... } tranne per il fatto che il primo fa quello che pensi faccia dove pensi che dovrebbe mentre il secondo fa cose strane a meno che non lo si avvolga in parens, ma che incasini l’oscilloscopio, e gli interpreti JS ti permettono di fare cose che sono considerate errori di syntax nelle specifiche così sei portato a credere che le cose sbagliate siano di fatto giuste, ecc ….

per favore usa le espressioni di funzione ( var f=function(){...} ). Non c’è una vera ragione per non farlo, specialmente considerando che sei un po ‘forzato a farlo quando usi la syntax del punto.


Sulla seconda cosa che hai toccato …..

Non sono sicuro di cosa dire, è un po ‘ diverso da tutto il resto.

 var foo = { baz: 43, doSomething:function() { ... } } 

questo è noto come syntax letterale dell’object. JSON, che si basa su questa syntax, è un modo abbastanza carino di formattare i dati , e questa syntax in JS è spesso usata per dichiarare nuovi oggetti, ad esempio con oggetti singleton (evitando tutto il casino con la dichiarazione di una funzione e l’uso di nuovi) . Può anche essere usato nello stesso modo in cui viene utilizzato XML, ed è preferito da tutti i bambini fantastici …

In ogni caso, la syntax letterale dell’object funziona in questo modo:

 { name1: val1, .... namek:valk } 

Questa espressione è un object con determinati valori inizializzati su di esso. così facendo var obj={ name1: val1, .... namek:valk } significa che:

 obj.name1==val1; obj['name1']==val1;// x['y'] is the same thing as xy ... obj.namek==valk; 

Che cosa ha a che fare con il nostro esempio? Fondamentalmente la tua espressione è spesso usata per dichiarare oggetti singleton. Ma può anche essere usato per dichiarare un prototipo di object, quindi qualcuno può in seguito var newObj = Object.create (foo), e newObj avrà foo come prototipo.

Guarda in dettaglio l’eredità prototipale se vuoi davvero capire quanto sia utile. Douglas Crockford ne parla in dettaglio in uno dei suoi numerosi discorsi).

Ci sono alcuni vantaggi nelle funzioni di denominazione

  • nomi per meta analisi. functionInstance.name ti mostrerà il nome.
  • Molto più importante, il nome verrà stampato in tracce dello stack.
  • i nomi aiutano anche a scrivere documenti autodidattici o scritti.

Esiste un solo svantaggio rispetto alle espressioni di funzioni denominate

  • IE ha perdite di memoria per NFE

Non ci sono svantaggi alle dichiarazioni di funzioni oltre al minor controllo stilistico

La tua domanda comprende in realtà due parti, in quanto non devi necessariamente rendere anonimi le tue funzioni se vengono assegnate a una variabile oa una proprietà.

Nominato vs anonimo?

@ Raynos evidenzia chiaramente i punti principali. La parte migliore delle funzioni con nome è che si mostreranno in una traccia stack. Anche nelle situazioni in cui le funzioni vengono assegnate a variabili / proprietà, è una buona idea assegnare un nome alle funzioni solo per facilitare il debug, tuttavia non direi che le funzioni anonime sono malvagie. Hanno uno scopo preciso:

Le funzioni anonime sono una ctriggers pratica in JavaScript?

Dichiarazione di funzione vs espressione di funzione?

Per quella parte della domanda ti rimanderò a questa domanda poiché probabilmente copre l’argomento in modo molto più approfondito di quanto possa io

var functionName = function () {} vs function functionName () {}