variable into inside create javascript function syntax idioms

javascript - into - var functionName=function(){} vs function functionName(){}



var function or function (30)

Aquí está el resumen de los formularios estándar que crean funciones: (Escrito originalmente para otra pregunta, pero adaptado después de pasar a la pregunta canónica).

Condiciones:

La lista rápida:

  • Declaración de funciones

  • Expresión de function "anónima" (que a pesar del término, a veces crea funciones con nombres)

  • Expresión de la function nombre

  • Inicializador de funciones de accesorios (ES5 +)

  • Expresión de la función de flecha (ES2015 +) (que, al igual que las expresiones de función anónimas, no implica un nombre explícito y, sin embargo, puede crear funciones con nombres)

  • Declaración de método en el inicializador de objetos (ES2015 +)

  • Declaraciones de constructores y métodos en class (ES2015 +)

Declaración de funciones

La primera forma es una declaración de función , que se ve así:

function x() { console.log(''x''); }

Una declaración de función es una declaración ; No es una declaración o expresión. Como tal, no lo sigues con una ; (aunque hacerlo es inofensivo).

Una declaración de función se procesa cuando la ejecución entra en el contexto en el que aparece, antes de que se ejecute cualquier código paso a paso. La función que crea recibe un nombre propio ( x en el ejemplo anterior), y ese nombre se coloca en el ámbito en el que aparece la declaración.

Debido a que se procesa antes de cualquier código paso a paso en el mismo contexto, puedes hacer cosas como estas:

x(); // Works even though it''s above the declaration function x() { console.log(''x''); }

Hasta ES2015, la especificación no cubría lo que debería hacer un motor de JavaScript si colocas una declaración de función dentro de una estructura de control como try , if , switch , while , etc., como esto:

if (someCondition) { function foo() { // <===== HERE THERE } // <===== BE DRAGONS }

Y como se procesan antes de ejecutar el código paso a paso, es difícil saber qué hacer cuando están en una estructura de control.

Aunque no se especificó hacer esto hasta ES2015, era una extensión permitida para admitir declaraciones de funciones en bloques. Desafortunadamente (e inevitablemente), diferentes motores hicieron cosas diferentes.

A partir de ES2015, la especificación dice qué hacer. De hecho, da tres cosas separadas para hacer:

  1. Si en modo suelto no está en un navegador web, el motor de JavaScript debe hacer una cosa
  2. Si está en modo suelto en un navegador web, se supone que el motor JavaScript debe hacer otra cosa.
  3. Si está en modo estricto (navegador o no), el motor de JavaScript debe hacer otra cosa más

Las reglas para los modos sueltos son complicadas, pero en modo estricto , las declaraciones de funciones en bloques son fáciles: son locales al bloque (tienen alcance de bloque , que también es nuevo en ES2015), y se elevan a la parte superior del bloque. Asi que:

"use strict"; if (someCondition) { foo(); // Works just fine function foo() { } } console.log(typeof foo); // "undefined" (`foo` is not in scope here // because it''s not in the same block)

Expresión de la function "anónima"

La segunda forma común se llama una expresión de función anónima :

var y = function () { console.log(''y''); };

Como todas las expresiones, se evalúa cuando se alcanza en la ejecución paso a paso del código.

En ES5, la función que crea no tiene nombre (es anónimo). En ES2015, a la función se le asigna un nombre si es posible inferiéndolo del contexto. En el ejemplo anterior, el nombre sería y . Algo similar se hace cuando la función es el valor de un inicializador de propiedad. (Para obtener detalles sobre cuándo sucede esto y las reglas, busque SetFunctionName en la especificación ; aparece en todas partes ).

Expresión de la function nombre

La tercera forma es una expresión de función nombrada ("NFE"):

var z = function w() { console.log(''zw'') };

La función que esto crea tiene un nombre propio ( w en este caso). Como todas las expresiones, esto se evalúa cuando se alcanza en la ejecución paso a paso del código. El nombre de la función no se agrega al ámbito en el que aparece la expresión; El nombre está dentro del alcance dentro de la función en sí:

var z = function w() { console.log(typeof w); // "function" }; console.log(typeof w); // "undefined"

Tenga en cuenta que las NFE con frecuencia han sido una fuente de errores para las implementaciones de JavaScript. IE8 y anteriores, por ejemplo, manejan las NFE de forma completamente incorrecta , creando dos funciones diferentes en dos momentos diferentes. Las primeras versiones de Safari también tenían problemas. La buena noticia es que las versiones actuales de los navegadores (IE9 y superiores, Safari actual) ya no tienen esos problemas. (Pero a la fecha de este escrito, lamentablemente, IE8 sigue siendo de uso generalizado, por lo que el uso de NFE con código para la web en general sigue siendo problemático).

Inicializador de funciones de accesorios (ES5 +)

A veces las funciones pueden pasar inadvertidas en gran medida; Ese es el caso de las funciones de acceso . Aquí hay un ejemplo:

var obj = { value: 0, get f() { return this.value; }, set f(v) { this.value = v; } }; console.log(obj.f); // 0 console.log(typeof obj.f); // "number"

Tenga en cuenta que cuando usé la función, no usé () ! Eso es porque es una función de acceso para una propiedad. Obtenemos y configuramos la propiedad de la forma normal, pero detrás de escena, se llama a la función.

También puede crear funciones de Object.defineProperty con Object.defineProperty , Object.defineProperties y el segundo argumento menos conocido de Object.create .

Expresión de la función de flecha (ES2015 +)

ES2015 nos trae la función de flecha . Aquí hay un ejemplo:

var a = [1, 2, 3]; var b = a.map(n => n * 2); console.log(b.join(", ")); // 2, 4, 6

Ver que n => n * 2 cosa oculta en el map() llamada? Esa es una función.

Un par de cosas sobre las funciones de flecha:

  1. Ellos no tienen su propio this . En su lugar, se cierran sobre el contexto donde están definidos. (También se cierran sobre los arguments y, cuando es relevante, super ). Esto significa que this dentro de ellos es el mismo donde se crearon y no se puede cambiar.

  2. Como habrá notado con lo anterior, no usa la function palabra clave; en su lugar, usas => .

El ejemplo n => n * 2 anterior es una forma de ellos. Si tiene varios argumentos para pasar la función, use parens:

var a = [1, 2, 3]; var b = a.map((n, i) => n * i); console.log(b.join(", ")); // 0, 2, 6

(Recuerde que Array#map pasa la entrada como primer argumento y el índice como segundo).

En ambos casos, el cuerpo de la función es solo una expresión; el valor de retorno de la función será automáticamente el resultado de esa expresión (no usa un return explícito).

Si está haciendo más que solo una expresión, use {} y un return explícito (si necesita devolver un valor), como de costumbre:

var a = [ {first: "Joe", last: "Bloggs"}, {first: "Albert", last: "Bloggs"}, {first: "Mary", last: "Albright"} ]; a = a.sort((a, b) => { var rv = a.last.localeCompare(b.last); if (rv === 0) { rv = a.first.localeCompare(b.first); } return rv; }); console.log(JSON.stringify(a));

La versión sin { ... } se denomina función de flecha con un cuerpo de expresión o un cuerpo conciso . (También: una función de flecha concisa ). El que tiene { ... } definiendo el cuerpo es una función de flecha con un cuerpo de función . (También: una función de flecha detallada ).

Declaración de método en el inicializador de objetos (ES2015 +)

ES2015 permite una forma más corta de declarar una propiedad que hace referencia a una función; se parece a esto:

var o = { foo() { } };

el equivalente en ES5 y anterior sería:

var o = { foo: function foo() { } };

Declaraciones de constructores y métodos en class (ES2015 +)

ES2015 nos brinda una sintaxis de class , incluidos los constructores y métodos declarados:

class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + " " + this.lastName; } }

Hay dos declaraciones de funciones anteriores: una para el constructor, que recibe el nombre de Person , y otra para getFullName , que es una función asignada a Person.prototype .

Recientemente comencé a mantener el código JavaScript de otra persona. Estoy corrigiendo errores, agregando características y también tratando de ordenar el código y hacerlo más consistente.

El desarrollador anterior usa dos formas de declarar funciones y no puedo resolver si hay una razón detrás de esto o no.

Las dos formas son:

var functionOne = function() { // Some code };

function functionTwo() { // Some code }

¿Cuáles son las razones para usar estos dos métodos diferentes y cuáles son los pros y los contras de cada uno? ¿Hay algo que se pueda hacer con un método que no se pueda hacer con el otro?


Estoy agregando mi propia respuesta solo porque todos los demás han cubierto la parte de elevación a fondo.

Me he preguntado qué camino es mejor durante mucho tiempo y, gracias a http://jsperf.com, ahora lo sé :)

Las declaraciones de funciones son más rápidas, y eso es lo que realmente importa en el desarrollo web, ¿no? ;)


Hablando sobre el contexto global, tanto la declaración var como una FunctionDeclaration al final crearán una propiedad no eliminable en el objeto global, pero el valor de ambos se puede sobrescribir .

La diferencia sutil entre las dos formas es que cuando se ejecuta el proceso de Instanciación de Variables (antes de la ejecución del código real) todos los identificadores declarados con var se inicializarán con undefined , y los utilizados por FunctionDeclaration estarán disponibles desde ese momento, por ejemplo. ejemplo:

alert(typeof foo); // ''function'', it''s already available alert(typeof bar); // ''undefined'' function foo () {} var bar = function () {}; alert(typeof bar); // ''function''

La asignación de la bar FunctionExpression tiene lugar hasta el tiempo de ejecución.

Una propiedad global creada por una FunctionDeclaration puede sobrescribirse sin ningún problema, como un valor variable, por ejemplo:

function test () {} test = null;

Otra diferencia obvia entre sus dos ejemplos es que la primera función no tiene un nombre, pero la segunda lo tiene, lo que puede ser realmente útil al depurar (es decir, inspeccionar una pila de llamadas).

Acerca de su primer ejemplo editado ( foo = function() { alert(''hello!''); }; ), Es una asignación no declarada, le recomiendo que use siempre la palabra clave var .

Con una asignación, sin la instrucción var , si el identificador al que se hace referencia no se encuentra en la cadena de alcance, se convertirá en una propiedad eliminable del objeto global.

Además, las asignaciones no declaradas arrojan un ReferenceError de ReferenceError en ECMAScript 5 en el modo estricto .

Una lectura obligada:

Nota : Esta respuesta se ha fusionado con otra pregunta , en la que la duda principal y la idea errónea del OP era que los identificadores declarados con una declaración de FunctionDeclaration no se podían sobrescribir, lo que no es el caso.


La diferencia es que functionOne es una expresión de función y, por lo tanto, solo se define cuando se alcanza esa línea, mientras que functionTwo es una declaración de función y se define tan pronto como se ejecuta su función o script circundante (debido a la hoisting ).

Por ejemplo, una expresión de función:

// TypeError: functionOne is not a function functionOne(); var functionOne = function() { console.log("Hello!"); };

Y, una declaración de función:

// Outputs: "Hello!" functionTwo(); function functionTwo() { console.log("Hello!"); }

Esto también significa que no puede definir funciones de forma condicional mediante declaraciones de funciones:

if (test) { // Error or misbehavior function functionThree() { doSomething(); } }

Lo anterior en realidad define la functionThree Tres independientemente del valor de la test , a menos que el use strict esté vigente, en cuyo caso simplemente genera un error.


Los dos fragmentos de código que has publicado allí, para casi todos los propósitos, se comportarán de la misma manera.

Sin embargo, la diferencia en el comportamiento es que con la primera variante ( var functionOne = function() {} ), a esa función solo se puede llamar después de ese punto en el código.

Con la segunda variante ( function functionTwo() ), la función está disponible para el código que se ejecuta arriba donde se declara la función.

Esto se debe a que con la primera variante, la función se asigna a la variable foo en tiempo de ejecución. En el segundo, la función se asigna a ese identificador, foo , en tiempo de análisis.

Más información técnica

JavaScript tiene tres formas de definir funciones.

  1. Tu primer fragmento muestra una función de expresión . Esto implica utilizar el operador "función" para crear una función: el resultado de ese operador se puede almacenar en cualquier variable o propiedad de objeto. La función de expresión es poderosa de esa manera. La expresión de función a menudo se denomina "función anónima", porque no tiene que tener un nombre,
  2. Su segundo ejemplo es una declaración de función . Esto utiliza la declaración de "función" para crear una función. La función está disponible en tiempo de análisis y puede invocarse en cualquier parte de ese ámbito. Aún puede almacenarlo en una variable o propiedad de objeto más tarde.
  3. La tercera forma de definir una función es el constructor "Función ()" , que no se muestra en tu publicación original. No se recomienda usar esto, ya que funciona de la misma manera que eval() , que tiene sus problemas.

Otros comentaristas ya han cubierto la diferencia semántica de las dos variantes anteriores. Quería notar una diferencia estilística: solo la variación de "asignación" puede establecer una propiedad de otro objeto.

A menudo construyo módulos de JavaScript con un patrón como este:

(function(){ var exports = {}; function privateUtil() { ... } exports.publicUtil = function() { ... }; return exports; })();

Con este patrón, todas sus funciones públicas usarán asignación, mientras que sus funciones privadas usan declaración.

(Tenga en cuenta también que la asignación debe requerir un punto y coma después de la declaración, mientras que la declaración lo prohíbe).


Primero quiero corregir a Greg: la function abc(){} tiene un ámbito, el nombre abc se define en el ámbito donde se encuentra esta definición. Ejemplo:

function xyz(){ function abc(){}; // abc is defined here... } // ...but not here

En segundo lugar, es posible combinar ambos estilos:

var xyz = function abc(){};

xyz se definirá como de costumbre, abc no está definido en todos los navegadores, pero Internet Explorer no confía en que se defina. Pero se definirá dentro de su cuerpo:

var xyz = function abc(){ // xyz is visible here // abc is visible here } // xyz is visible here // abc is undefined here

Si desea crear alias de funciones en todos los navegadores, use este tipo de declaración:

function abc(){}; var xyz = abc;

En este caso, tanto xyz como abc son alias del mismo objeto:

console.log(xyz === abc); // prints "true"

Una razón convincente para usar el estilo combinado es el atributo "nombre" de los objetos de función ( no es compatible con Internet Explorer ). Básicamente cuando se define una función como

function abc(){}; console.log(abc.name); // prints "abc"

Su nombre se asigna automáticamente. Pero cuando lo definas como

var abc = function(){}; console.log(abc.name); // prints ""

su nombre está vacío: creamos una función anónima y la asignamos a alguna variable.

Otra buena razón para usar el estilo combinado es usar un nombre interno corto para referirse a sí mismo, mientras se proporciona un nombre largo y no conflictivo para usuarios externos:

// Assume really.long.external.scoped is {} really.long.external.scoped.name = function shortcut(n){ // Let it call itself recursively: shortcut(n - 1); // ... // Let it pass itself as a callback: someFunction(shortcut); // ... }

En el ejemplo anterior, podemos hacer lo mismo con un nombre externo, pero será demasiado difícil de manejar (y más lento).

(Otra forma de referirse a sí mismo es usar arguments.callee , que todavía es relativamente largo y no se admite en el modo estricto).

En el fondo, JavaScript trata ambas afirmaciones de manera diferente. Esta es una declaración de función:

function abc(){}

abc aquí se define en todas partes en el alcance actual:

// We can call it here abc(); // Works // Yet, it is defined down there. function abc(){} // We can call it again abc(); // Works

Además, se levantó a través de una declaración de return :

// We can call it here abc(); // Works return; function abc(){}

Esta es una expresión de función:

var xyz = function(){};

Aquí se define xyz desde el punto de asignación:

// We can''t call it here xyz(); // UNDEFINED!!! // Now it is defined xyz = function(){} // We can call it here xyz(); // works

La declaración de función frente a la expresión de función es la razón real por la que Greg demuestra una diferencia.

Hecho de la diversión:

var xyz = function abc(){}; console.log(xyz.name); // Prints "abc"

Personalmente, prefiero la declaración de "expresión de función" porque de esta manera puedo controlar la visibilidad. Cuando defino la función como

var abc = function(){};

Sé que definí la función localmente. Cuando defino la función como

abc = function(){};

Sé que lo definí globalmente siempre que no definí abc en ninguna parte de la cadena de ámbitos. Este estilo de definición es resistente incluso cuando se utiliza dentro de eval() . Mientras que la definición

function abc(){};

depende del contexto y puede dejarte adivinar dónde está realmente definido, especialmente en el caso de eval() ; la respuesta es: depende del navegador.


Una ilustración de cuándo preferir el primer método al segundo es cuando debe evitar anular las definiciones anteriores de una función.

Con

if (condition){ function myfunction(){ // Some code } }

, esta definición de myfunction anulará cualquier definición anterior, ya que se realizará en tiempo de análisis.

Mientras

if (condition){ var myfunction = function (){ // Some code } }

hace el trabajo correcto de definir myfunction solo cuando se cumple la condition .


Una mejor explicación para la respuesta de Greg.

functionTwo(); function functionTwo() { }

¿Por qué no hay error? Siempre nos enseñaron que las expresiones se ejecutan de arriba a abajo (??)

Porque:

Las declaraciones de funciones y las declaraciones de variables siempre se mueven ( hoisted ) invisiblemente al principio de su alcance de contenido por el intérprete de JavaScript. Los parámetros de función y los nombres definidos por el idioma están, obviamente, ya están allí. ben cherry

Esto significa que el código como este:

functionOne(); --------------- var functionOne; | is actually | functionOne(); var functionOne = function(){ | interpreted |--> }; | like | functionOne = function(){ --------------- };

Tenga en cuenta que la porción de asignación de las declaraciones no se elevó. Sólo el nombre es izado.

Pero en el caso de las declaraciones de funciones, todo el cuerpo de la función también será izado :

functionTwo(); --------------- function functionTwo() { | is actually | }; function functionTwo() { | interpreted |--> } | like | functionTwo(); ---------------


Una razón importante es agregar una y solo una variable como la "Raíz" de su espacio de nombres ...

var MyNamespace = {} MyNamespace.foo= function() { }

o

var MyNamespace = { foo: function() { }, ... }

Hay muchas técnicas para el espacio de nombres. Se ha vuelto más importante con la gran cantidad de módulos de JavaScript disponibles.

Consulte también ¿Cómo declaro un espacio de nombres en JavaScript?


da un ejemplo donde nombra una función asignada para poder usarlashortcut() como una referencia interna de sí misma. John Resig da otro ejemplo: copiar una función recursiva asignada a otro objeto en su tutorial de aprendizaje avanzado de Javascript . Si bien la asignación de funciones a propiedades no es estrictamente la cuestión aquí, recomiendo probar el tutorial de manera activa; ejecute el código haciendo clic en el botón en la esquina superior derecha y haga doble clic en el código para editarlo a su gusto.

Ejemplos del tutorial: llamadas recursivas en yell():

Las pruebas fallan cuando se elimina el objeto ninja original. (página 13)

var ninja = { yell: function(n){ return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "A single object isn''t too bad, either." ); var samurai = { yell: ninja.yell }; var ninja = null; try { samurai.yell(4); } catch(e){ assert( false, "Uh, this isn''t good! Where''d ninja.yell go?" ); }

Si nombra la función que se llamará recursivamente, las pruebas pasarán. (página 14)

var ninja = { yell: function yell(n){ return n > 0 ? yell(n-1) + "a" : "hiy"; } }; assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); var samurai = { yell: ninja.yell }; var ninja = {}; assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );


new Function()se puede utilizar para pasar el cuerpo de la función en una cadena. Y por lo tanto esto puede ser usado para crear funciones dinámicas. También pasando el script sin ejecutar el script.

var func = new Function("x", "y", "return x*y;"); function secondFunction(){ var result; result = func(10,20); console.log ( result ); } secondFunction()


Hoisting es la acción del intérprete de JavaScript de mover todas las declaraciones de variables y funciones a la parte superior del alcance actual.

Sin embargo, solo se elevan las declaraciones reales. dejando las tareas donde están.

  • Las variables / funciones declaradas dentro de la página son globales y pueden acceder a cualquier parte de esa página.
  • Las funciones / variable declaradas dentro de la función tienen alcance local. significa que están disponibles / accedidos dentro del cuerpo de la función (alcance), no están disponibles fuera del cuerpo de la función.

Variable

Javascript se llama lenguaje vagamente escrito. Lo que significa que las variables de Javascript pueden contener el valor de cualquier tipo de Data-Type . Javascript se encarga automáticamente de cambiar el tipo de variable en función del valor / literal proporcionado durante el tiempo de ejecución.

global_Page = 10; var global_Page; « undefined « Integer literal, Number Type. ------------------- global_Page = 10; « Number global_Page = ''Yash''; | Interpreted | global_Page = ''Yash''; « String « String literal, String Type. « AS « global_Page = true; « Boolean var global_Page = true; | | global_Page = function (){ « function « Boolean Type ------------------- var local_functionblock; « undefined global_Page = function (){ local_functionblock = 777;« Number var local_functionblock = 777; }; // Assigning function as a data. };

Función

function Identifier_opt ( FormalParameterList_opt ) { FunctionBody | sequence of statements « return; Default undefined « return ''some data''; }

  • Las funciones declaradas dentro de la página se elevan a la parte superior de la página con acceso global.
  • Las funciones declaradas dentro del bloque de funciones se elevan a la parte superior del bloque.
  • El valor de retorno predeterminado de la función es '' undefined '', el valor predeterminado de la declaración de Variable también es ''indefinido''

    Scope with respect to function-block global. Scope with respect to page undefined | not available.

Declaración de funciones

function globalAccess() { function globalAccess() { } ------------------- } globalAccess(); | | function globalAccess() { « Re-Defined / overridden. localAccess(); « Hoisted As « function localAccess() { function globalAccess() { | | } localAccess(); ------------------- localAccess(); « function accessed with in globalAccess() only. function localAccess() { } } globalAccess(); } localAccess(); « ReferenceError as the function is not defined

Expresión de la función

10; « literal (10); « Expression (10).toString() -> ''10'' var a; a = 10; « Expression var a.toString() -> ''10'' (function invoke() { « Expression Function console.log(''Self Invoking''); (function () { }); }) () -> ''Self Invoking'' var f; f = function (){ « Expression var Function console.log(''var Function''); f () -> ''var Function'' };

Función asignada a la variable Ejemplo:

(function selfExecuting(){ console.log(''IIFE - Immediately-Invoked Function Expression''); }()); var anonymous = function (){ console.log(''anonymous function Expression''); }; var namedExpression = function for_InternalUSE(fact){ if(fact === 1){ return 1; } var localExpression = function(){ console.log(''Local to the parent Function Scope''); }; globalExpression = function(){ console.log(''creates a new global variable, then assigned this function.''); }; //return; //undefined. return fact * for_InternalUSE( fact - 1); }; namedExpression(); globalExpression();

javascript interpretado como

var anonymous; var namedExpression; var globalExpression; anonymous = function (){ console.log(''anonymous function Expression''); }; namedExpression = function for_InternalUSE(fact){ var localExpression; if(fact === 1){ return 1; } localExpression = function(){ console.log(''Local to the parent Function Scope''); }; globalExpression = function(){ console.log(''creates a new global variable, then assigned this function.''); }; return fact * for_InternalUSE( fact - 1); // DEFAULT UNDEFINED. }; namedExpression(10); globalExpression();

Puede verificar la declaración de la función, la prueba de expresión en diferentes navegadores usando jsperf Test Runner

ES5 Constructor Function Classes : objetos de función creados con Function.prototype.bind

JavaScript trata las funciones como objetos de primera clase, por lo que al ser un objeto, puede asignar propiedades a una función.

function Shape(id) { // Function Declaration this.id = id; }; // Adding a prototyped method to a function. Shape.prototype.getID = function () { return this.id; }; Shape.prototype.setID = function ( id ) { this.id = id; }; var expFn = Shape; // Function Expression var funObj = new Shape( ); // Function Object funObj.hasOwnProperty(''prototype''); // false funObj.setID( 10 ); console.log( funObj.getID() ); // 10

ES6 introdujo la función de flecha : una expresión de función de flecha tiene una sintaxis más corta, son las más adecuadas para las funciones que no son de método y no pueden utilizarse como constructores.

ArrowFunction : ArrowParameters => ConciseBody .

const fn = (item) => { return item & 1 ? ''Odd'' : ''Even''; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd


Sobre el rendimiento:

Nuevas versiones de V8introdujeron varias optimizaciones bajo el capó y así lo hicieron SpiderMonkey.

Casi no hay diferencia ahora entre expresión y declaración.
La expresión de la función parece ser más rápida ahora.

Cromo 62.0.3202

FireFox 55

Canario Cromo 63.0.3225


AnonymousLas expresiones de función parecen tener un mejor rendimiento contra la Namedexpresión de función.


Firefox Chrome Canary Chrome


A la luz del argumento de que "las funciones con nombre aparecen en rastros de pila", los motores de JavaScript modernos son en realidad bastante capaces de representar funciones anónimas.

A partir de este escrito, V8, SpiderMonkey, Chakra y Nitro siempre se refieren a funciones nombradas por sus nombres. Casi siempre se refieren a una función anónima por su identificador, si tiene una.

SpiderMonkey puede averiguar el nombre de una función anónima devuelta por otra función. El resto no puede.

Si realmente quieres que tu iterador y las devoluciones de llamada de éxito aparezcan en la traza, también puedes nombrarlas ...

[].forEach(function iterator() {});

Pero en su mayor parte no vale la pena subrayar.

Arnés ( Fiddle )

''use strict''; var a = function () { throw new Error(); }, b = function b() { throw new Error(); }, c = function d() { throw new Error(); }, e = { f: a, g: b, h: c, i: function () { throw new Error(); }, j: function j() { throw new Error(); }, k: function l() { throw new Error(); } }, m = (function () { return function () { throw new Error(); }; }()), n = (function () { return function n() { throw new Error(); }; }()), o = (function () { return function p() { throw new Error(); }; }()); console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) { return values.concat(e[key]); }, [])).concat([m, n, o]).reduce(function (logs, func) { try { func(); } catch (error) { return logs.concat(''func.name: '' + func.name + ''/n'' + ''Trace:/n'' + error.stack); // Need to manually log the error object in Nitro. } }, []).join(''/n/n''));

V8

func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at a (http://localhost:8000/test.js:4:11) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: b Trace: Error at b (http://localhost:8000/test.js:7:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: d Trace: Error at d (http://localhost:8000/test.js:10:15) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at e.i (http://localhost:8000/test.js:17:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: j Trace: Error at j (http://localhost:8000/test.js:20:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: l Trace: Error at l (http://localhost:8000/test.js:23:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: Trace: Error at http://localhost:8000/test.js:28:19 at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: n Trace: Error at n (http://localhost:8000/test.js:33:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 func.name: p Trace: Error at p (http://localhost:8000/test.js:38:19) at http://localhost:8000/test.js:47:9 at Array.reduce (native) at http://localhost:8000/test.js:44:27 test.js:42

Mono araña

func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: a@http://localhost:8000/test.js:4:5 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: b Trace: b@http://localhost:8000/test.js:7:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: d Trace: d@http://localhost:8000/test.js:10:9 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: e.i@http://localhost:8000/test.js:17:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: j Trace: j@http://localhost:8000/test.js:20:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: l Trace: l@http://localhost:8000/test.js:23:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: Trace: m</<@http://localhost:8000/test.js:28:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: n Trace: n@http://localhost:8000/test.js:33:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1 func.name: p Trace: p@http://localhost:8000/test.js:38:13 @http://localhost:8000/test.js:47:9 @http://localhost:8000/test.js:54:1

Chakra

func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at a (http://localhost:8000/test.js:4:5) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at b (http://localhost:8000/test.js:7:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at d (http://localhost:8000/test.js:10:9) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at e.i (http://localhost:8000/test.js:17:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at j (http://localhost:8000/test.js:20:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at l (http://localhost:8000/test.js:23:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at Anonymous function (http://localhost:8000/test.js:28:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at n (http://localhost:8000/test.js:33:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1) func.name: undefined Trace: Error at p (http://localhost:8000/test.js:38:13) at Anonymous function (http://localhost:8000/test.js:47:9) at Global code (http://localhost:8000/test.js:42:1)

Nitro

func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: a@http://localhost:8000/test.js:4:22 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: b Trace: b@http://localhost:8000/test.js:7:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: d Trace: d@http://localhost:8000/test.js:10:26 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: i@http://localhost:8000/test.js:17:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: j Trace: j@http://localhost:8000/test.js:20:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: l Trace: l@http://localhost:8000/test.js:23:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: Trace: http://localhost:8000/test.js:28:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: n Trace: n@http://localhost:8000/test.js:33:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33 func.name: p Trace: p@http://localhost:8000/test.js:38:30 http://localhost:8000/test.js:47:13 reduce@[native code] global code@http://localhost:8000/test.js:44:33


El primer ejemplo es una declaración de función:

function abc(){}

El segundo ejemplo es una expresión de función:

var abc = function() {};

La principal diferencia es cómo se levantan (se levantan y se declaran). En el primer ejemplo, la declaración de la función completa es izada. En el segundo ejemplo, solo se levanta la var ''abc'', su valor (la función) quedará indefinido y la función en sí permanecerá en la posición en que se declara.

Para hacerlo mas simple:

//this will work abc(param); function abc(){} //this would fail abc(param); var abc = function() {}

Para estudiar más sobre este tema te recomiendo este link


En JavaScript hay dos formas de crear funciones:

  1. Declaración de función:

    function fn(){ console.log("Hello"); } fn();

    Esto es muy básico, se explica por sí mismo, se usa en muchos idiomas y es estándar en toda la familia C de idiomas. Declaramos que una función la definió y la ejecutamos llamándola.

    Lo que deberías saber es que las funciones son en realidad objetos en JavaScript; internamente hemos creado un objeto para la función anterior y le hemos dado un nombre llamado fn o la referencia al objeto se almacena en fn Las funciones son objetos en JavaScript; una instancia de función es en realidad una instancia de objeto.

  2. Expresión de la función:

    var fn=function(){ console.log("Hello"); } fn();

    JavaScript tiene funciones de primera clase, es decir, crea una función y la asigna a una variable de la misma manera que creas una cadena o número y la asignas a una variable Aquí, la variable fn se asigna a una función. La razón de este concepto es que las funciones son objetos en JavaScript; fn está apuntando a la instancia de objeto de la función anterior. Hemos inicializado una función y la hemos asignado a una variable. No está ejecutando la función y asignando el resultado.

Referencia: sintaxis de la declaración de la función de JavaScript: var fn = function () {} vs function fn () {}


En términos del costo de mantenimiento del código, las funciones nombradas son más preferibles:

  • Independiente del lugar donde se declaran (pero aún están limitados por el alcance).
  • Más resistente a los errores, como la inicialización condicional (todavía puede anular si lo desea).
  • El código se vuelve más legible al asignar funciones locales por separado de la funcionalidad del alcance. Por lo general, en el ámbito de aplicación, la funcionalidad va primero, seguida de declaraciones de funciones locales.
  • En un depurador, verá claramente el nombre de la función en la pila de llamadas en lugar de una función "anónima / evaluada".

Sospecho que se siguen más PROS para funciones con nombre. Y lo que se enumera como una ventaja de las funciones nombradas es una desventaja para las funciones anónimas.

Históricamente, las funciones anónimas aparecían de la incapacidad de JavaScript como lenguaje para enumerar miembros con funciones nombradas:

{ member:function() { /* How do I make "this.member" a named function? */ } }


Estas son solo dos formas posibles de declarar funciones y, en segundo lugar, puede usar la función antes de declarar.


Estoy enumerando las diferencias a continuación:

  1. Una declaración de función se puede colocar en cualquier parte del código. Incluso si se invoca antes de que la definición aparezca en el código, se ejecuta a medida que la declaración de la función se confirma en la memoria o, de alguna manera, se eleva, antes de que se inicie cualquier otro código en la página.

    Echa un vistazo a la función de abajo:

    function outerFunction() { function foo() { return 1; } return foo(); function foo() { return 2; } } alert(outerFunction()); // Displays 2

    Esto se debe a que, durante la ejecución, parece que:

    function foo() { // The first function declaration is moved to top return 1; } function foo() { // The second function declaration is moved to top return 2; } function outerFunction() { return foo(); } alert(outerFunction()); //So executing from top to bottom, //the last foo() returns 2 which gets displayed

    Una expresión de función, si no se define antes de llamarla, dará como resultado un error. Además, aquí la definición de la función en sí no se mueve a la parte superior ni se confirma en la memoria como en las declaraciones de funciones. Pero la variable a la que asignamos la función se eleva y la indefinida se le asigna.

    La misma función que usa expresiones de función:

    function outerFunction() { var foo = function() { return 1; } return foo(); var foo = function() { return 2; } } alert(outerFunction()); // Displays 1

    Esto es porque durante la ejecución, se ve así:

    function outerFunction() { var foo = undefined; var foo = undefined; foo = function() { return 1; }; return foo (); foo = function() { // This function expression is not reachable return 2; }; } alert(outerFunction()); // Displays 1

  2. No es seguro escribir declaraciones de funciones en bloques no funcionales como si no fueran accesibles.

    if (test) { function x() { doSomething(); } }

  3. Es posible que una expresión de función con nombre como la que aparece a continuación no funcione en los navegadores de Internet Explorer anteriores a la versión 9.

    var today = function today() {return new Date()}


Hay tres comparaciones notables entre las dos diferentes declaraciones de funciones que se enumeran a continuación.

  1. Disponibilidad (alcance) de la función

Lo siguiente funciona porque function add()está limitado al bloque más cercano:

try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } function add(a, b){ return a + b; }

Lo siguiente no funciona (porque los var add=superseeds function add()).

try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } var add=function add(a, b){ return a + b; }

Lo siguiente no funciona porque addse declara después de su uso.

try { console.log("Success: ", add(1, 1)); } catch(e) { console.log("ERROR: " + e); } var add=function(a, b){ return a + b; }

  1. (función) .nombre

El nombre de una función function thefuncname(){}es thefuncname cuando se declara de esta manera.

function foobar(a, b){} console.log(foobar.name);

var a = function foobar(){}; console.log(a.name);

De lo contrario, si una función se declara como function(){}, la función .name es la primera variable utilizada para almacenar la función.

var a = function(){}; var b = (function(){ return function(){} }); console.log(a.name); console.log(b.name);

Si no hay variables configuradas para la función, entonces el nombre de las funciones es la cadena vacía ( "").

console.log((function(){}).name === "");

Por último, mientras la variable a la que está asignada la función establece inicialmente el nombre, las variables sucesivas establecidas en la función no cambian el nombre.

var a = function(){}; var b = a; var c = b; console.log(a.name); console.log(b.name); console.log(c.name);

  1. Actuación

En V8 de Google y en Spidermonkey de Firefox puede haber una diferencia de compilación JIST de pocos microsegundos, pero en última instancia el resultado es el mismo. Para probar esto, examinemos la eficiencia de JSPerf en microbenchmarks comparando la velocidad de dos fragmentos de código en blanco. Las pruebas de JSPerf se encuentran aquí . Y, las pruebas jsben.ch se encuentran aquí . Como puede ver, hay una diferencia notable cuando no debería haber ninguna. Si realmente eres un fanático del rendimiento como yo, entonces quizás valga más la pena intentar reducir el número de variables y funciones en el ámbito y, especialmente, eliminar el polimorfismo (como usar la misma variable para almacenar dos tipos diferentes).

Cuál es el "bloque más cercano"

El "bloque más cercano" es la "función" más cercana (incluidas las funciones asíncronas, las funciones del generador y las funciones del generador asíncrono). Sin embargo, de manera interesante, a se function functionName() {}comporta como un objeto var functionName = function() {}cuando está en un bloque que no está cerrado a elementos fuera de dicho cierre. Observar.

  • Normal var add=function(){}

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}''); } } catch(e) { console.log("Is a block"); } var add=function(a, b){return a + b}

  • Normal function add(){}

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}'') } } catch(e) { console.log("Is a block"); } function add(a, b){ return a + b; }

  • Función

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}'') } } catch(e) { console.log("Is a block"); } (function () { function add(a, b){ return a + b; } })();

  • Declaración (como if, else, for, while, try/ catch/ finally, switch, do/ while, with)

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}'') } } catch(e) { console.log("Is a block"); } { function add(a, b){ return a + b; } }

  • Función de flecha con var add=function()

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}'') } } catch(e) { console.log("Is a block"); } (() => { var add=function(a, b){ return a + b; } })();

  • Función de flecha con function add()

try { // typeof will simply return "undefined" if the variable does not exist if (typeof add !== "undefined") { add(1, 1); // just to prove it console.log("Not a block"); }else if(add===undefined){ // this throws an exception if add doesn''t exist console.log(''Behaves like var add=function(a,b){return a+b}'') } } catch(e) { console.log("Is a block"); } (() => { function add(a, b){ return a + b; } })();


La primera (función doSomething (x)) debe ser parte de una notación de objeto.

El segundo ( var doSomething = function(x){ alert(x);}) es simplemente crear una función anónima y asignarlo a una variable, doSomething. Así que doSomething () llamará a la función.

Es posible que desee saber qué es una declaración de función y una expresión de función .

Una declaración de función define una variable de función nombrada sin requerir asignación de variable. Las declaraciones de funciones se producen como construcciones independientes y no se pueden anidar dentro de bloques que no son de función.

function foo() { return 3; }

ECMA 5 (13.0) define la sintaxis como
identificador de función ( opción FormalParameterList ) {FunctionBody}

En la condición anterior, el nombre de la función es visible dentro de su alcance y el alcance de su principal (de lo contrario, sería inalcanzable)

Y en una expresión de función.

Una expresión de función define una función como parte de una sintaxis de expresión más grande (generalmente una asignación de variable). Las funciones definidas a través de expresiones de funciones pueden ser nombradas o anónimas. Las expresiones de función no deben comenzar con "función".

// Anonymous function expression var a = function() { return 3; } // Named function expression var a = function foo() { return 3; } // Self-invoking function expression (function foo() { alert("hello!"); })();

ECMA 5 (13.0) define la sintaxis como
identificador de función opt (FormalParameterList opt ) {FunctionBody}


La respuesta de Greg es suficientemente buena, pero todavía me gustaría agregarle algo que aprendí hace un momento viendo videos de Douglas Crockford .

Expresión de la función:

var foo = function foo() {};

Declaración de la función:

function foo() {};

La declaración de función es solo una abreviatura de vardeclaración con un functionvalor.

Asi que

function foo() {};

se expande a

var foo = function foo() {};

Que se expande aún más a:

var foo = undefined; foo = function foo() {};

Y ambos están en la parte superior del código.


Otra diferencia que no se menciona en las otras respuestas es que si usa la función anónima

var functionOne = function() { // Some code };

y usar eso como un constructor como en

var one = new functionOne();

entonces one.constructor.nameno será definido. Function.nameno es estándar pero es compatible con Firefox, Chrome, otros navegadores derivados de Webkit e IE 9+.

Con

function functionTwo() { // Some code } two = new functionTwo();

es posible recuperar el nombre del constructor como una cadena con two.constructor.name.


Si usas esas funciones para crear objetos, obtendrás:

var objectOne = new functionOne(); console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function var objectTwo = new functionTwo(); console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function


Son bastante similares con algunas pequeñas diferencias, la primera es una variable que se asigna a una función anónima (Declaración de función) y la segunda es la forma normal de crear una función en JavaScript (Declaración de función anónima), ambas tienen uso, desventajas y ventajas :

1. Expresión de la función

var functionOne = function() { // Some code };

Una expresión de función define una función como parte de una sintaxis de expresión más grande (normalmente una asignación de variable). Funciones definidas a través de Funciones Las expresiones pueden ser nombradas o anónimas. Las expresiones de función no deben comenzar con "función" (por lo tanto, los paréntesis alrededor del ejemplo que se invoca a continuación).

Asignar una variable a una función, significa que no hay Elevación, ya que sabemos que las funciones en JavaScript pueden Elevar, significa que pueden llamarse antes de que se declaren, mientras que las variables deben declararse antes de acceder a ellas, así que en este caso no podemos acceda a la función antes de que se declare, también podría ser una forma de escribir sus funciones, para las funciones que devuelven otra función, este tipo de declaración podría tener sentido, también en ECMA6 y más arriba puede asignar esto a una función de flecha que puede utilizarse para llamar a funciones anónimas, también esta forma de declaración es una mejor manera de crear funciones de Constructor en JavaScript.

2. Declaración de la función

function functionTwo() { // Some code }

Una declaración de función define una variable de función nombrada sin requerir asignación de variable. Las declaraciones de funciones se producen como construcciones independientes y no se pueden anidar dentro de bloques que no son de función. Es útil pensar en ellos como hermanos de declaraciones variables. Al igual que las Declaraciones de variables deben comenzar con "var", las Declaraciones de funciones deben comenzar con "function".

Esta es la forma normal de llamar a una función en JavaScript, se puede llamar a esta función incluso antes de declararla ya que en JavaScript todas las funciones son Hoisted, pero si tiene "uso estricto" no se Hoist como se espera, es una buena manera para llamar a todas las funciones normales que no son grandes en líneas y ninguna es una función constructora.

Además, si necesita más información sobre cómo funciona la elevación en JavaScript, visite el siguiente enlace:

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting


Una declaración de función y una expresión de función asignada a una variable se comportan igual una vez que se establece el enlace.

Sin embargo, hay una diferencia en cómo y cuándo el objeto de función está realmente asociado con su variable. Esta diferencia se debe al mecanismo llamado elevación de variables en JavaScript.

Básicamente, todas las declaraciones de funciones y declaraciones de variables se colocan en la parte superior de la función en la que se produce la declaración (es por esto que decimos que JavaScript tiene un alcance de función ).

  • Cuando se eleva una declaración de función, el cuerpo de la función "sigue", de modo que cuando se evalúa el cuerpo de la función, la variable se vinculará inmediatamente a un objeto de función.

  • Cuando se eleva una declaración de variable, la inicialización no sigue, sino que se "deja atrás". La variable se inicializa al undefinedcomienzo del cuerpo de la función y se le asigna un valor en su ubicación original en el código. (En realidad, se le asignará un valor en cada ubicación donde ocurra una declaración de una variable con el mismo nombre).

El orden de elevación también es importante: las declaraciones de función tienen prioridad sobre las declaraciones de variables con el mismo nombre, y la última declaración de función tiene prioridad sobre las declaraciones de función anteriores con el mismo nombre.

Algunos ejemplos...

var foo = 1; function bar() { if (!foo) { var foo = 10 } return foo; } bar() // 10

La variable foose eleva a la parte superior de la función, se inicializa a undefined, por lo que !fooes true, así foose asigna 10. El fooexterior del baralcance de ''no juega ningún papel y está intacto.

function f() { return a; function a() {return 1}; var a = 4; function a() {return 2}} f()() // 2 function f() { return a; var a = 4; function a() {return 1}; function a() {return 2}} f()() // 2

Las declaraciones de función tienen prioridad sobre las declaraciones de variables, y la última declaración de función se "pega".

function f() { var a = 4; function a() {return 1}; function a() {return 2}; return a; } f() // 4

En este ejemplo, ase inicializa con el objeto de función que resulta de evaluar la segunda declaración de función y luego se asigna 4.

var a = 1; function b() { a = 10; return; function a() {}} b(); a // 1

Aquí la declaración de función se eleva primero, declarando e inicializando la variable a. A continuación, se asigna esta variable 10. En otras palabras: la asignación no se asigna a la variable externa a.


Utilizo el enfoque variable en mi código por una razón muy específica, cuya teoría se ha tratado de manera abstracta anteriormente, pero un ejemplo podría ayudar a algunas personas como yo, con experiencia limitada en JavaScript.

Tengo el código que necesito para ejecutar con 160 marcas de diseño independiente. La mayoría del código está en archivos compartidos, pero las cosas específicas de la marca están en un archivo separado, uno para cada marca.

Algunas marcas requieren funciones específicas y otras no. A veces tengo que agregar nuevas funciones para hacer nuevas cosas específicas de la marca. Estoy feliz de cambiar el código compartido, pero no quiero tener que cambiar los 160 conjuntos de archivos de marca.

Al usar la sintaxis de la variable, puedo declarar la variable (un puntero a la función esencialmente) en el código compartido y asignar una función de trivial stub, o establecerla en nula.

Las una o dos marcas que necesitan una implementación específica de la función pueden definir su versión de la función y asignarla a la variable si así lo desean, y el resto no hacer nada. Puedo probar una función nula antes de ejecutarla en el código compartido.

A partir de los comentarios de la gente de arriba, deduzco que también es posible redefinir una función estática, pero creo que la solución variable es agradable y clara.


Ambas son formas diferentes de definir una función. La diferencia es cómo el navegador los interpreta y los carga en un contexto de ejecución.

El primer caso es de expresiones de función que se cargan solo cuando el intérprete llega a esa línea de código. Por lo tanto, si lo hace como se indica a continuación, obtendrá un error de que functionOne no es una función .

functionOne(); var functionOne = function() { // Some code };

El motivo es que en la primera línea no se asigna ningún valor a functionOne y, por lo tanto, no está definido. Estamos tratando de llamarlo como una función, y por lo tanto estamos recibiendo un error.

En la segunda línea estamos asignando la referencia de una función anónima a functionOne.

El segundo caso es de declaraciones de funciones que se cargan antes de ejecutar cualquier código. Entonces, si le gusta lo siguiente, no obtendrá ningún error, ya que la declaración se carga antes de la ejecución del código.

functionOne(); function functionOne() { // Some code }


En términos informáticos, hablamos de funciones anónimas y funciones nombradas. Creo que la diferencia más importante es que una función anónima no está vinculada a un nombre, de ahí la función anónima de nombre. En JavaScript es un objeto de primera clase declarado dinámicamente en tiempo de ejecución.

Para obtener más información sobre las funciones anónimas y el cálculo lambda, Wikipedia es un buen comienzo ( http://en.wikipedia.org/wiki/Anonymous_function ).