Alcance y elevación de la función Javascript


Acabo de leer un gran artículo sobre JavaScript Scoping and Hoisting por Ben Cherry en el que da el siguiente ejemplo:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

Usando el código anterior, el navegador alertará a "1".

Todavía no estoy seguro de por qué devuelve "1". Algunas de las cosas que dice vienen a la mente como: Todas las declaraciones de funciones se elevan a la parte superior. Puede definir el alcance de una variable mediante function. Todavía no funciona para mí.

Author: thefourtheye, 2011-09-22

14 answers

El levantamiento de funciones significa que las funciones se mueven a la parte superior de su alcance. Es decir,

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

Será reescrito por el interpeter a este

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

Raro, ¿eh?

También, en este caso,

function a() {}

Se comportó igual que

var a = function () {};

Así que, en esencia, esto es lo que el código está haciendo:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"
 103
Author: Peter Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-10 20:11:48

Lo que debe recordar es que analiza toda la función y resuelve todas las declaraciones de variables antes de ejecutarla. Tan....

function a() {} 

Realmente se convierte en

var a = function () {}

var a lo fuerza en un ámbito local, y el ámbito variable es a través de toda la función, por lo que la variable global a sigue siendo 1 porque ha declarado a en un ámbito local convirtiéndolo en una función.

 6
Author: kemiller2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-21 21:27:31

La función a se ho dentro de la función b:

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

Que es casi como usar var:

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

La función se declara localmente, y la configuración a solo ocurre en el ámbito local, no en el var global.

 5
Author: Digital Plane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-21 21:30:52
  1. la declaración de función function a(){} se eleva primero y se comporta como var a = function () {};, por lo tanto en el ámbito local se crea a.
  2. Si tiene dos variables con el mismo nombre (una en global y otra en local), la variable local siempre tiene prioridad sobre la variable global.
  3. Cuando establece a=10, está configurando la variable local a , no la global.

Por lo tanto, el valor de la variable global sigue siendo el mismo y se obtiene, alertado 1

 3
Author: KhanSharp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-17 13:52:15

function a() { } es una sentencia function, que crea una variable a local a la función b.
Las variables se crean cuando se analiza una función, independientemente de si se ejecuta la instrucción var o function.

a = 10 establece esta variable local.

 1
Author: SLaks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-21 21:29:46

Scpope & closure & hoisting (var/function)

  1. scpope: el var global se puede acceder en cualquier lugar(el archivo completo ámbito), el var local solo puede ser accedido por el local scope (function / block scope)!
    Nota: si una variable local no utiliza var palabras clave en una función, se convertirá en una variable global!
  2. cierre: una función interna de la otra función, que puede acceder ámbito local ( función padre) y ámbito global, howerver es vars no puede ser accedido por otros! a menos que, su retorno como valor de retorno!
  3. elevación: mueva todos los var/undeclare/función al ámbito arriba, que asignar el valor o null!
    Nota: ¡solo mueve la declaración, no mueve el valor!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined
 1
Author: xgqfrms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-17 14:25:22

La elevación es un concepto hecho para que sea más fácil de entender. Lo que realmente sucede es que las declaraciones se hacen primero con respecto a sus ámbitos y las asignaciones sucederán después de eso(no al mismo tiempo).

Cuando suceden las declaraciones, var a, entonces function b y dentro de ese ámbito b, se declara function a.

Esta función a sombreará la variable a procedente del ámbito global.

Después de hacer las declaraciones, los valores asignados comenzarán, el a global obtendrá el valor 1 y la a dentro de function b obtendrá 10. cuando haga alert(a), llamará a la variable de ámbito global real. Este pequeño cambio en el código lo hará más claro

        var a = 1;

    function b() {
        a = 10;
        return a;

        function a() { }
    }

    alert(b());
    alert(a);
 1
Author: Bazzzzzzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-21 13:05:41

Está sucediendo porque el nombre de la variable es el mismo que el nombre de la función significa "a". Por lo tanto, debido a que Javascript lo eleva, intente resolver el conflicto de nombres y devolverá a = 1.

También estaba confundido acerca de esto hasta que leí este post en" JavaScript Hoisting " http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Espero que ayude.

 0
Author: AugustRush,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-16 12:55:54

Aquí está mi resumen de la respuesta con más anotación y un violín acompañante para jugar.

// hoisting_example.js

// top of scope ie. global var a = 1
var a = 1;

// new scope due to js' functional (not block) level scope
function b() {
    a = 10; // if the function 'a' didn't exist in this scope, global a = 10
  return; // the return illustrates that function 'a' is hoisted to top
  function a(){}; // 'a' will be hoisted to top as var a = function(){};
}

// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b' 
// and in doing so, created a new named variable 'a' 
// which is a function within b's scope
b();

// a will alert 1, see comment above
alert(a);

Https://jsfiddle.net/adjavaherian/fffpxjx7 /

 0
Author: 4m1r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-09 18:41:35

¿Cuál es la manzana de la discordia en este pequeño fragmento de código?

Caso 1:

Incluir function a(){} definición dentro del cuerpo de function b como sigue. logs value of a = 1

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

  function a() {}
}
b();
console.log(a); // logs a = 1

Caso 2

Excluir function a(){} definición dentro del cuerpo de function b como sigue. logs value of a = 10

var a = 1;
function b() {
  a = 10;  // overwrites the value of global 'var a'
  return;
}
b();
console.log(a); // logs a = 10

La observación le ayudará a darse cuenta de que la instrucción console.log(a) registra los siguientes valores.

Caso 1: a = 1

Caso 2: a = 10

Posts

  1. var a ha sido definido y declarado léxicamente en el ámbito global.
  2. a=10 Esta declaración es reasignar valor a 10, se encuentra léxicamente dentro de la función b.

Explicación de ambos casos

Debido a function definition with name property a es lo mismo que variable a. El variable a dentro del function body b se convierte en una variable local. La línea anterior implica que el valor global de a permanece intacto y el valor local de a es actualizado a 10.

Entonces, lo que pretendemos decir es que el siguiente código

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

  function a() {}
}
b();
console.log(a); // logs a = 1

Es interpretado por el intérprete de JS de la siguiente manera.

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


}
b();
console.log(a); // logs a = 1

Sin embargo, cuando eliminamos el function a(){} definition, el value of 'a' declarado y definido fuera de la función b, ese valor se sobrescribe y cambia a 10 en el caso 2. El valor se sobrescribe porque a=10 se refiere a la declaración global y si se declarara localmente debemos haber escrito var a = 10;.

var a = 1;
function b() {
  var a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;
}
b();
console.log(a); // logs a = 1

Podemos aclarar aún más nuestra duda cambiando el name property en function a(){} definition a algún otro nombre que 'a'

var a = 1;
function b() {
  a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;

  function foo() {}
}
b();
console.log(a); // logs a = 1
 0
Author: Sagar Munjal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-21 15:35:25

Levantar en JavaScript significa que las declaraciones de variables se ejecutan a través del programa antes de que se ejecute cualquier código. Por lo tanto, declarar una variable en cualquier parte del código es equivalente a declararla al principio.

 0
Author: Vishwas S L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-14 22:13:24

Todo depende del alcance de la variable 'a'. Permítanme explicar mediante la creación de ámbitos como imágenes.

Aquí JavaScript creará 3 ámbitos.

I) Ámbito global. ii) Función b () alcance. iii) Ámbito de la función a ().

introduzca la descripción de la imagen aquí

Se borra cuando se llama al método 'alert' el ámbito pertenece a Global ese tiempo, por lo que recogerá el valor de la variable 'a' del ámbito Global solo que es 1.

 0
Author: Sumit Pahuja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-28 15:51:06

Long Post!

¡Pero limpiará el aire!

La forma en que funciona Java Script es que implica un proceso de dos pasos: {[18]]}

  1. Compilación (por así decirlo) - Este paso registra variables y declaraciones de funciones y su respectivo alcance. No implica evaluar la expresión de la función: var a = function(){} o la expresión variable (como asignar 3 a x en el caso de var x =3; que no es más que la evaluación de la parte R. H. S.)

  2. Intérprete: es la parte de ejecución / evaluación.

Compruebe la salida del siguiente código para obtener un entendimiento:

//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);

function b() {
  //cannot write the below line:
  //console.log(e); 
  //since e is not declared.
  e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
  console.log("e is " + e) //  works!
  console.log("f is " + f);
  var f = 7;
  console.log("Now f is " + f);
  console.log("d is " + d);
  return;

  function d() {}
}
b();
console.log(a);

Vamos a romperlo:

  1. En la fase de compilación, "a" se registraría en el ámbito global con el valor " undefined". Lo mismo ocurre con ' c', su valor en este momento sería 'undefined' y no el 'function()'. "b " se registraría como una función en el ámbito mundial. Dentro del ámbito de aplicación de b, 'f ' se registraría como se registraría una variable que no estaría definida en este momento y la función 'd'.

  2. Cuando se ejecuta el intérprete, se puede acceder a las variables declaradas y function() (y no a las expresiones) antes de que el intérprete alcance la línea de expresión real. Por lo tanto, las variables se imprimirían 'undefined' y la función anónima declarada se puede llamar antes. Sin embargo, intentar acceder a una variable no declarada antes de la inicialización de su expresión resultaría en un error me gusta:

console.log(e)
e = 3;

Ahora, qué sucede cuando se tiene una declaración de variable y función con el mismo nombre.

La respuesta es - las funciones siempre se izan antes y si se declara la variable del mismo nombre, se trata como duplicada e ignorada. Recuerda, el orden no importa. Las funciones siempre tienen prioridad. Pero durante la fase de evaluación puede cambiar la variable referencia a cualquier cosa (Almacena lo que fue la última asignación) Echa un vistazo al siguiente código:

var a = 1;
console.log("a is " + a);

function b() {
  console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
  a = 3; //a changed
  console.log("Now a is " + a);
  return;

  function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.
 0
Author: pragun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-21 13:19:46

Hoisting es el concepto de comportamiento de JavaScript. Elevación (digamos movimiento) es un concepto que explica cómo y dónde se deben declarar las variables.

En JavaScript, una variable se puede declarar después de que se ha utilizado porque las declaraciones de función y las declaraciones de variable siempre se mueven ("izadas") invisiblemente a la parte superior de su ámbito de contenido por el intérprete de JavaScript.

Nos encontramos con dos tipos de elevación en la mayoría de los casos.

1.Declaración de variables elevación

Vamos a entender esto por este pedazo de código.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Aquí la declaración de la variable a será alojada de forma invisible por el intérprete javascript en el momento de la compilación. Así que fuimos capaces de obtener valor de a. Pero este enfoque de declaración de variables no se recomienda como debemos declarar variables a la parte superior ya como esto.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

Considere otro ejemplo.

  function foo() {
     console.log(x)
     var x = 1;
 }

En realidad se interpreta así:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

En este caso x será indefinido

No importa si se ha ejecutado el código que contiene la declaración de variable. Considere este ejemplo.

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

Esta función resulta ser así.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

En la declaración de variables solo los polipastos de definición de variables, no la asignación.

  1. Declaración de función de elevación

A diferencia de la variable hoisting, también se izará el cuerpo de la función o el valor asignado. Considere este código

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

Ahora como hemos entendido tanto la variable y la función de elevación, vamos a entender este código ahora.

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

Este código resultará ser así.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

La función a() tendrá un ámbito local dentro de b(). a () se moverá a la parte superior mientras interpreta el código con su definición (solo en caso de elevación de la función), por lo que a ahora tendrá un alcance local y, por lo tanto, no afectará el alcance global de a mientras tenga su propio alcance dentro de la función b ().

 0
Author: Must keem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-26 07:30:15