[Javascript] var functionName = function () {} vs function functionName () {}


Answers

Primero quiero corregir a Greg: la function abc(){} tiene un alcance: el nombre abc se define en el alcance 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 va a definir como siempre, abc no está definido en todos los navegadores, pero Internet Explorer: no confíe en que esté definido. 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 alias 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 admitidos por Internet Explorer ). Básicamente cuando defines una función como

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

su nombre es asignado automáticamente. Pero cuando lo defines 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, al tiempo que proporciona un nombre largo y no conflictivo para los 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 declaraciones 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 izó 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(){};

xyz aquí se define 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 la función frente a la expresión de la función es la verdadera razón por la cual hay una diferencia demostrada por Greg.

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 forma 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 usa dentro de eval() . Mientras que la definición

function abc(){};

depende del contexto y puede hacer que adivine dónde está realmente definido, especialmente en el caso de eval() - la respuesta es: depende del navegador.

Question

Recientemente comencé a mantener el código de JavaScript de otra persona. Estoy arreglando errores, agregando funciones 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 o no.

Las dos formas son:

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

¿Cuáles son las razones para utilizar 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 puede hacer con el otro?




They are pretty similar with some small differences, first one is a variable which assigned to an anonymous function (Function Declaration) and second one is the normal way to create a function in JavaScript(Anonymous function Declaration), both has usage, cons and pros:

1. Function Expression

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

A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via Functions Expressions can be named or anonymous. Function Expressions must not start with “function” (hence the parentheses around the self invoking example below).

Assign a variable to a function, means no Hoisting, as we know functions in JavaScript can Hoist, means they can be called before they get declared, while variables need to be declared before getting access to them, so means in this case we can not access the function before where it's declared, also it could be a way that you write your functions, for the functions which return another function, this kind of declaration could make sense, also in ECMA6 & above you can assign this to an arrow function which can be used to call anonymous functions, also this way of declaring is a better way to create Constructor functions in JavaScript.

2. Function Declaration

function functionTwo() {
    // Some code
}

A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. It's helpful to think of them as siblings of Variable Declarations. Just as Variable Declarations must start with “var”, Function Declarations must begin with “function”.

This is the normal way of calling a function in JavaScript, this function can be called before you even declare it as in JavaScript all functions get Hoisted, but if you have 'use strict' this won't Hoist as expected, it's a good way to call all normal functions which are not big in lines and neither are a constructor function.

Also, if you need more info about how hoisting works in JavaScript, visit the link below:

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




Hablando sobre el contexto global, ambos, la sentencia var y una FunctionDeclaration al final crearán una propiedad no eliminable en el objeto global, pero el valor de ambos puede sobrescribirse .

La sutil diferencia entre las dos formas es que cuando se ejecuta el proceso de ejecución de variables (antes de la ejecución real del código) todos los identificadores declarados con var se inicializan con undefined , y los que usa FunctionDeclaration estarán disponibles desde ese momento, para 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 se puede sobrescribir sin ningún problema, al igual que un valor variable, por ejemplo:

 function test () {}
 test = null;

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

Acerca de su primer ejemplo editado ( foo = function() { alert('hello!'); }; ), Es una tarea no declarada, le recomiendo encarecidamente que siempre use 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 del alcance, se convertirá en una propiedad que se puede eliminar del objeto global.

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

Una lectura obligada:

Nota : Esta respuesta se ha fusionado con otra pregunta , en la que la principal duda y error de OP era que los identificadores declarados con una FunctionDeclaration no podían sobrescribirse, lo cual no es el caso.




If you would use those functions to create objects, you would get:

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



A function declaration and a function expression assigned to a variable behave the same once the binding is established.

There is a difference however at how and when the function object is actually associated with its variable. This difference is due to the mechanism called variable hoisting in JavaScript.

Basically, all function declarations and variable declarations are hoisted to the top of the function in which the declaration occurs (this is why we say that JavaScript has function scope ).

  • When a function declaration is hoisted, the function body "follows" so when the function body is evaluated, the variable will immediately be bound to a function object.

  • When a variable declaration is hoisted, the initialization does not follow, but is "left behind". The variable is initialized to undefined at the start of the function body, and will be assigned a value at its original location in the code. (Actually, it will be assigned a value at every location where a declaration of a variable with the same name occurs.)

The order of hoisting is also important: function declarations take precedence over variable declarations with the same name, and the last function declaration takes precedence over previous function declarations with the same name.

Some examples...

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

Variable foo is hoisted to the top of the function, initialized to undefined , so that !foo is true , so foo is assigned 10 . The foo outside of bar 's scope plays no role and is untouched.

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

Function declarations take precedence over variable declarations, and the last function declaration "sticks".

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

In this example a is initialized with the function object resulting from evaluating the second function declaration, and then is assigned 4 .

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

Here the function declaration is hoisted first, declaring and initializing variable a . Next, this variable is assigned 10 . In other words: the assignment does not assign to outer variable a .




gives an example where he names an assigned function to be able to use shortcut() as an internal reference to itself. John Resig gives another example - copying a recursive function assigned to another object in his Learning Advanced Javascript tutorial. While assigning functions to properties isn't strictly the question here, I recommend actively trying the tutorial out - run the code by clicking the button in the upper right corner, and double click the code to edit to your liking.

Examples from the tutorial: recursive calls in yell() :

Tests fail when the original ninja object is removed. (page 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?" ); 
}

If you name the function that will be called recursively, the tests will pass. (page 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." );



In terms of code maintenance cost, named functions are more preferable:

  • Independent from the place where they are declared (but still limited by scope).
  • More resistant to mistakes like conditional initialization (you are still able to override if wanted to).
  • The code becomes more readable by allocating local functions separately of scope functionality. Usually in the scope the functionality goes first, followed by declarations of local functions.
  • In a debugger you will clearly see the function name on the call stack instead of an "anonymous/evaluated" function.

I suspect more PROS for named functions are follow. And what is listed as an advantage of named functions is a disadvantage for anonymous ones.

Historically, anonymous functions appeared from the inability of JavaScript as a language to list members with named functions:

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



This is just two possible ways of declaring functions, and in the second way, you can use the function before declaration.




There are three main differences between the two different declarations of functions as listed below.

  1. Availability (scope) of the function

The following works because function add() is scoped to the nearest block:

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

function add(a, b){
  return a + b;
}

The following does not works (because the var add= superseeds the function add() ).

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

var add=function add(a, b){
  return a + b;
}

The following does not work because add is declared after it is used.

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

var add=function(a, b){
  return a + b;
}

  1. (function) .name

The name of a function function thefuncname(){} is thefuncname when it is declared this way.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

Otherwise, if a function is declared as function(){} , the function .name is the first variable used to store the function.

var a = function(){};
var b = (function(){ return function(){} });

console.log(a.name);
console.log(b.name);

If there are no variables set to the function, then the functions name is the empty string ( "" ).

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

Lastly, while the variable the function is assigned to initially sets the name, successive variables set to he function do not change the name.

var a = function(){};
var b = a;
var c = b;

console.log(a.name);
console.log(b.name);
console.log(c.name);

  1. Performance In Google's V8 and Firefox's Spidermonkey there might be a few microsecond JIST compilation difference, but ultimately the result is the exact same. To prove this, let's examine the efficiency of JSPerf at microbenchmarks by comparing the speed of two blank code snippets. The JSPerf tests are found here . And, the jsben.ch testsare found here . As you can see, there is a noticable difference when there should be none. If you are really a performance freak like me, then it might be more worth your while trying to reduce the number of variables and functions in the scope and especially eliminating polymorphism (such as using the same variable to store two different types).



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

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

  • las variables / Funciones declaradas dentro de la página son globales pueden acceder a cualquier parte de esa página.
  • las variables / Funciones 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 sin tipeo. Lo que significa que las variables de Javascript pueden contener el valor de cualquier tipo de Data-Type . Javascript se ocupa 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 que tiene 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 la Variable también '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

Clases de funciones de constructor de ES5 : 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 más adecuadas para funciones que no son de método y no se pueden usar como constructores.

ArrowFunction : ArrowParameters => ConciseBody .

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



In JavaScript there are two ways to create functions:

  1. Function declaration:

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

    This is very basic, self-explanatory, used in many languages and standard across C family of languages. We declared a function defined it and executed it by calling it.

    What you should be knowing is that functions are actually objects in JavaScript; internally we have created an object for above function and given it a name called fn or the reference to the object is stored in fn. Functions are objects in JavaScript; an instance of function is actually an object instance.

  2. Function expression:

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

    JavaScript has first-class functions, that is, create a function and assign it to a variable just like you create a string or number and assign it to a variable. Here, the fn variable is assigned to a function. The reason for this concept is functions are objects in JavaScript; fn is pointing to the object instance of the above function. We have initialized a function and assigned it to a variable. It's not executing the function and assigning the result.

Reference: JavaScript function declaration syntax: var fn = function() {} vs function fn() {}




In computer science terms, we talk about anonymous functions and named functions. I think the most important difference is that an anonymous function is not bound to an name, hence the name anonymous function. In JavaScript it is a first class object dynamically declared at runtime.

For more information on anonymous functions and lambda calculus, Wikipedia is a good start ( http://en.wikipedia.org/wiki/Anonymous_function ).




Una ilustración de cuándo preferir el primer método al segundo es cuando necesita evitar anular las definiciones previas 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 declaraciones de variables siempre se mueven ( hoisted ) invisiblemente a la parte superior de su ámbito de contenido por el intérprete de JavaScript. Los parámetros de función y los nombres definidos en el lenguaje obviamente ya están allí. Ben Cherry

Esto significa que código como este:

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

Tenga en cuenta que la parte de asignación de las declaraciones no fueron izadas. Solo el nombre es izado.

Pero en el caso de las declaraciones de función, también se izará todo el cuerpo de la función :

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



The first one (function doSomething(x)) should be part of an object notation.

The second one ( var doSomething = function(x){ alert(x);} ) is simply creating an anonymous function and assigning it to a variable, doSomething . So doSomething() will call the function.

You may want to know what a function declaration and function expression is.

A function declaration defines a named function variable without requiring variable assignment. Function declarations occur as standalone constructs and cannot be nested within non-function blocks.

function foo() {
    return 3;
}

ECMA 5 (13.0) defines the syntax as
function Identifier ( FormalParameterList opt ) { FunctionBody }

In above condition the function name is visible within its scope and the scope of its parent (otherwise it would be unreachable).

And in a function expression

A function expression defines a function as a part of a larger expression syntax (typically a variable assignment ). Functions defined via functions expressions can be named or anonymous. Function expressions should not start with “function”.

// 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) defines the syntax as
function Identifier opt ( FormalParameterList opt ) { FunctionBody }