Declaración de función como var en lugar de función

28

Cada vez veo más funciones declaradas como

var foo = function() {

    // things
};

En lugar de cómo había aprendido, como

function foo() {

    // things
}

¿Cual es la diferencia? ¿Mejor presentación? ¿Alcance? ¿Debo estar usando este método?

Steve Robbins
fuente
Vale la pena señalar que en JavaScript, las funciones son ciudadanos de primera clase . Esto le permite transmitir el comportamiento al igual que los objetos. Esto es muy útil para devoluciones de llamada y delegación, entre otras cosas.
Chris Bye
Ámbito de aplicación . El ajuste de nombre de variable "// cosas" esencialmente / con suerte previene la colisión de nombres de "// cosas" que está envolviendo, con otros JavaScript (archivos) incluidos. Otra forma de pensarlo es que ha creado un espacio de nombres "foo".
radarbob

Respuestas:

25

var foo = function() {} define una variable que hace referencia a una función anónima.

function foo() {}define una función con nombre foo.

Se puede pasar por nombre como parámetros de función y se puede instanciar si el uso previsto es para OOP.

Al final del día, cuál usa usted está en gran medida dictado por su caso de uso específico (Javascript es divertido así;)). Si al final el uso de la antigua, me fuertemente sugieren que nombre la función:

var foo = function MY_function() {}. Esta convención de nomenclatura ayuda a que su pila de llamadas del depurador no sea inútil.

Demian Brecht
fuente
1
Tengo una tontería en la función () MI ...
Erik Reppen
1
@Demian Brecht, y ¿qué pasa con el enfoque var foo = function foo () {...}?
shabunc
@shabunc: ¿Qué hay de eso? Está listado en el último párrafo de mi respuesta.
Demian Brecht
@Demian Brecht, no, en realidad en el último párrafo se llama a la variable y se llama a la foofunciónMY_function
shabunc
@shabunc: El nombre no importa. Lo que importa es el valor en la pila de llamadas. Como ejemplo, [NAMESPACE] _ [nombre fn] es la convención utilizada por Mozilla. El nombre en sí no importa siempre y cuando su convención sea coherente en todo su proyecto.
Demian Brecht
13

expresión de función:

//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };

La expresión func en este caso es anónima pero se asigna a una var como referencia. Esto es diferente de una declaración de función etiquetada de las siguientes maneras:

  • no se puede izar (se llama antes de que se defina)
  • new someFunction().constructor.name === 'someFunction';//false las instancias no obtienen el nombre var para constructor.name porque se asigna una referencia a la función a la var pero la var, no la función, está vinculada al nombre var

En una declaración de función etiquetada:

//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
  • trabajos de elevación
  • new someFunction().constructor.name === 'someFunction'; //true el nombre está vinculado directamente a la función.

En términos generales, no hay una buena razón para hacer una expresión en var a menos que desee que las llamadas fallen si las cosas se mueven o si está definiendo / asignando un método en una línea. De hecho, encuentro que el izado es útil para organizar objetos con funciones internas y definiciones de métodos en la parte inferior para poder llegar al comportamiento real del objeto y hacer definiciones de métodos públicos de una línea (simplemente asignando funciones this.con el mismo nombre) todo en uno lugar para facilitar la referencia. Siempre debe intentar usar declaraciones etiquetadas para constructores, IMO, para que pueda identificar el 'tipo' de un objeto a través de su constructor.

Erik Reppen
fuente
8

Su primer ejemplo es una expresión, mientras que el segundo ejemplo es una declaración . La definición de funciones como expresiones permite una mayor flexibilidad en el lugar donde puede aparecer la definición, a qué puede asignarla, que puede pasarla como parámetro, etc.

Por ejemplo:

SomeThing('abc', function(a,b) {return a*b;});

vs ...

function tmp(a,b) { 
    return a*b;
}

SomeThing('abc', tmp);

Los ejemplos más complejos se volverían oblicuamente complicados sin la sintaxis de expresión de función.

Mira /programming/111102/how-do-javascript-closures-work

gahooa
fuente
4

La principal diferencia práctica es la elevación. Por ejemplo:

foo(); // alerts 'hello'
function foo() {alert('hello');}

vs

foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}

Además, este es un comportamiento indefinido

function foo(){
  if (true) {
    function bar(){}
  }
  bar();
}

mientras esto está bien.

function foo(){
  if (true) {
    var bar = function(){}
  }
  bar();
}
Austin
fuente
77
No hay absolutamente nada de malo en definir una función dentro de una función en JS. No hay muchos lugares en los que no pueda definir una función en JS.
Erik Reppen
2
@ErikReppen Definitivamente no puede usar una declaración de función dentro de bloques que no sean de función (como dentro de una declaración if). Parece que no puedo encontrar donde leo, no se pueden usar dentro de otra función.
Austin
@Austin ¡Tampoco tiene nada de malo una definición de función dentro de una ifdeclaración!
Tim
@Austin: ¿Quizás lo leíste en w3schools? ;)
Demian Brecht
2
@ErikReppen Las expresiones de función se pueden usar en cualquier lugar. Las declaraciones de funciones no pueden ser. Ver stackoverflow.com/questions/10069204/…
Austin