Alcance y elevación de funciones de Javascript


90

Acabo de leer un gran artículo sobre JavaScript Scoping and Hoisting de 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 están subidas a la parte superior. Puede medir una variable usando function. Todavía no me hace clic.

Respuestas:


120

La elevación 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 intérprete a este

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

Extraño, ¿eh?

Además, en este caso,

function a() {}

se comportó igual que

var a = function () {};

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

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"

2
Entonces, ¿todas las declaraciones de funciones finalmente se asignan a una variable?
dev.e.loper

15
@ dev.e.loper Sí, en Javascript, las funciones son objetos de primera clase, como cadenas y números. Eso significa que se definen como variables y se pueden pasar a otras funciones, almacenarse en matrices, etc.
Peter Olson

4
De ninguna manera se "reescribe" el cuerpo de la función. Los diversos estándares de ECMAScript establecen claramente que las declaraciones de variables y funciones se procesan antes de que comience la ejecución del código. Es decir, nada se mueve , se trata de orden de ejecución (de ahí mi disgusto por el término "izar", que infiere movimiento o reordenamiento). En su código reescrito, la declaración var adebe estar antes de la declaración de función y la asignación a = 1debe estar después. Pero tenga en cuenta que el analizador, el tokenizador, el intérprete, el compilador, lo que sea, no especifica que esto suceda realmente , es solo un equivalente.
RobG

3
@RobG Claro, supongo que podría llamar a la descripción una pequeña "mentira a los niños" , pero al final el comportamiento es el mismo, ya sea que el código se reorganice literalmente o simplemente se reorganice el orden de ejecución. Lo que realmente sucede detrás de escena es más una preocupación académica, e incluso podría depender de la implementación.
Peter Olson

7
"Además, en este caso, se function a() {}comportó igual que var a = function () {};"  - esto es incorrecto de dos maneras: primero, en todo caso, habría sido var a = function a() {};(la función en realidad no es anónima), segundo, esas dos formas no son intercambiables, porque de var a = function a() {};sólo la var a;parte habría sido izada. La a = function a() {};parte aún estaría detrás de la declaración de devolución. Debido a que la forma original es una declaración de función y no una expresión de función, en realidad se eleva como un todo.
user4642212

6

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

function a() {} 

realmente se convierte en

var a = function () {}

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


5

La función ase eleva 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 asolo ocurre en el ámbito local, no en la var global.


1
esta línea "var a = function () {};" deja todo en claro ... básicamente JavaScript es un lenguaje dinámico y "function" también es un objeto en JavaScript.
refactorización

3
  1. La declaración de función function a(){}se eleva primero y se comporta como var a = function () {};, por lo tanto, ase crea el alcance local .
  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 configura 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 recibe una alerta 1


1

function a() { }es una declaración de función, que crea una avariable local a la bfunción.
Las variables se crean cuando se analiza una función, independientemente de si varse ejecuta la instrucción de la función o.

a = 10 establece esta variable local.


de hecho, a = 10establece una variable en el ámbito global cuando bse ejecuta la función, a menos que usted agregue "use strict"(en entornos como el soporte de esa directiva).
Sean Vieira

@Sean: No, porque la declaración de función crea un identificador local.
SLaks

... y .... tienes razón. No se había dado cuenta de la consecuencia particular de la función de elevación. ¡Gracias!
Sean Vieira

1

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

Caso 1:

Incluya la function a(){}definición dentro del cuerpo de la function bsiguiente manera.logs value of a = 1

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

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

Caso 2

Excluya la function a(){}definición dentro del cuerpo de function blo siguiente.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 declaración console.log(a)registra los siguientes valores.

Caso 1: a = 1

Caso 2: a = 10

Posiciones

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

Explicación de ambos casos

Debido a que function definition with name propertya es igual que variable a. El variable ainterior se function body bconvierte en una variable local. La línea anterior implica que el valor global de a permanece intacto y el valor local de a se actualiza 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

El intérprete de JS lo interpreta 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 se a=10refiere a la declaración global y si fuera a declararse localmente, debemos tener 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 nuestras dudas aún más por el cambio de la name propertyde function a(){} definitiona algún otro nombre de'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

1

Izar es un concepto creado para nosotros para que sea más fácil de entender. Lo que realmente sucede es que las declaraciones se hacen primero con respecto a sus alcances y las asignaciones ocurrirán después de eso (no al mismo tiempo).

Cuando ocurren las declaraciones var a, entonces function by dentro de ese balcance, function ase declara.

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

Después de las declaraciones se hacen, los valores de asignación se iniciará, lo global ase obtendrá el valor 1y el interior de una function bobtendrá 10. cuando lo haga alert(a), llamará a la variable de alcance 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
Es curioso que tantos expertos incluso en un curso de codeschool.com se refieran a izar, que no es más que una visión simplista de lo que sucede, en realidad izar no ocurre en absoluto. Ref: 1) developer.mozilla.org/en-US/docs/Glossary/Hoisting 2) Capítulo 5 de Secrets of the JavaScript Ninja 2 / e por john resig, bear bebeault, josip maras
adnan2nd

1

Sorprendentemente, ninguna de las respuestas aquí menciona la relevancia del contexto de ejecución en la cadena de alcance.

El motor de JavaScript envuelve el código que se está ejecutando actualmente en un contexto de ejecución. El contexto de ejecución base es el contexto de ejecución global. Cada vez que se invoca una nueva función, se crea un nuevo contexto de ejecución y se coloca en la pila de ejecución. Piense en un Stack Frame sentado en una Invocation Stack en otros lenguajes de programación. Último en entrar primero en salir. Ahora, cada contexto de ejecución tiene su propio entorno variable y entorno externo en JavaScript.

Usaré el siguiente ejemplo como demostración.

1) Primero, ingresamos a la Fase de Creación del Contexto de Ejecución global. Se crean tanto el entorno exterior como el entorno variable del entorno léxico. El Objeto Global se configura y se coloca en la memoria con la variable especial 'this' apuntándolo. La función ay su código y la variable myVar con un valor indefinido se colocan en la memoria del entorno variable global. es importante tener en cuenta que el código de la función a no se ejecuta. Simplemente se coloca en la memoria con la función a.

2) En segundo lugar, es la fase de ejecución del contexto de ejecución. myVar ya no es un valor indefinido. Se inicializa con el valor 1, que se almacena en el entorno variable global. Se invoca la función a y se crea un nuevo contexto de ejecución.

3) En el contexto de ejecución de la función a, pasa por la fase de creación y ejecución de su propio contexto de ejecución. Tiene su propio entorno exterior y entorno variable, por lo tanto, su propio entorno léxico. La función by la variable myVar se almacenan en su entorno variable. Este entorno variable es distinto del entorno variable global. Dado que la función a se encuentra léxica (físicamente en el código) en el mismo nivel que el contexto de ejecución global, su entorno externo es el contexto de ejecución global. Por lo tanto, si la función a se refería a una variable que no está en su Entorno de Variables, buscará la Cadena de Alcance e intentará encontrar la variable en el Entorno de Variables del Contexto de Ejecución global.

4) La función b se invoca en la función a. Se crea un nuevo contexto de ejecución. Dado que se encuentra léxicamente en la función a, su entorno externo es a. Entonces, cuando hace referencia a myVar, dado que myVar no está en el entorno variable de la función b, buscará en el entorno variable de la función a. Lo encuentra allí y console.log imprime 2. Pero si la variable no estaba en el Entorno variable de la función a, entonces dado que el Entorno externo de la función a es el Contexto de ejecución global, la Cadena de alcance continuará buscando allí.

5) Una vez finalizada la ejecución de las funciones by a, se extraen de la pila de ejecución. El motor JavaScript de un solo subproceso continúa la ejecución en el contexto de ejecución global. Invoca la función b. Pero no hay función b en el entorno variable global y no hay otro entorno exterior para buscar en el contexto de ejecución global. Por lo tanto, el motor JavaScript genera una excepción.

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

  var myVar = 2;
  b();
}

var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined

El siguiente ejemplo muestra la cadena de alcance en acción. En el entorno variable del contexto de ejecución de la función b, no hay myVar. Entonces busca su entorno exterior, que es la función a. La función a tampoco tiene myVar en su entorno variable. Entonces, el motor busca el entorno externo de la función a, que es el entorno externo del contexto de ejecución global y myVar se define allí. Por lo tanto, console.log imprime 1.

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

  b();
}

var myVar = 1;
a();
> 1

Con respecto al contexto de ejecución y el entorno léxico asociado con él, incluido el entorno externo y el entorno variable, habilite el alcance de las variables en JavaScript. Incluso si invoca la misma función varias veces, para cada invocación, creará su propio contexto de ejecución. Entonces, cada Contexto de Ejecución tendrá su propia copia de las variables en su Entorno de Variables. No se comparten las variables.


0

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 la elevación de Javascript, intenta resolver el conflicto de nombres y devolverá a = 1.

También estaba confundido acerca de esto hasta que leí esta publicación sobre "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Espero eso ayude.


0

Aquí está mi resumen de la respuesta con más anotaciones 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

scpope y cierre y elevación (var / función)

  1. scpope: se puede acceder a la var global en cualquier lugar (todo el alcance del archivo), ¡solo se puede acceder a la var local mediante el alcance local (función / alcance de bloque)!
    Nota: si una variable local no usa palabras clave var en una función, ¡se convertirá en una variable global!
  2. cierre: una función dentro de la otra función, que puede acceder al alcance local (función principal) y al alcance global, ¡sin embargo, otros no pueden acceder a sus variables! a menos que lo devuelva como valor de retorno.
  3. izar: mover todas las variables / funciones declarar / anular la declaración a la parte superior del alcance, luego asignar el valor o nulo.
    Nota: ¡solo mueve el declare, 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



0

Elevación En JavaScript significa que las declaraciones de variables se ejecutan en todo el programa antes de que se ejecute cualquier código. Por lo tanto, declarar una variable en cualquier parte del código equivale a declararla al principio.


0

Todo depende del alcance de la variable 'a'. Déjame explicarte creando ámbitos como imágenes.

Aquí JavaScript creará 3 ámbitos.

i) Alcance global. ii) Alcance de la función b (). iii) Función a () alcance.

ingrese la descripción de la imagen aquí

Está claro cuando llama al alcance del método 'alerta' que pertenece a Global en ese momento, por lo que seleccionará el valor de la variable 'a' del alcance global solo que sea 1.


0

¡Mensaje largo!

¡Pero aclarará el aire!

La forma en que funciona Java Script es que implica un proceso de dos pasos:

  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 función: var a = function(){}o expresión de variable (como asignar 3a xen caso de var x =3;que no sea más que la evaluación de la parte RHS).

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

Verifique el resultado del siguiente código para comprenderlo:

//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, se registraría 'a' en alcance global con 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 global. Dentro bdel alcance, fse registraría como una variable indefinida en ese momento y dse registraría la función.

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

console.log(e)
e = 3;

Ahora, ¿qué sucede cuando tienes una declaración de variable y función con el mismo nombre?

La respuesta es : las funciones siempre se levantan antes y si se declara la misma variable de nombre, se trata como duplicada y se ignora. Recuerde, el orden no importa. Las funciones siempre tienen prioridad. Pero durante la fase de evaluación, puede cambiar la referencia de la variable a cualquier cosa (almacena lo que fue la última asignación) Eche 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

Izar es un concepto de comportamiento de JavaScript. Izar (digamos mover) 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 haya utilizado porque las declaraciones de función y las declaraciones de variable siempre se mueven ("levantan") de manera invisible a la parte superior de su alcance contenedor por el intérprete de JavaScript.

Encontramos dos tipos de izado en la mayoría de los casos.

1.Alzado de declaración variable

Entendamos esto por este fragmento 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 en la parte superior de forma invisible por el intérprete de JavaScript en el momento de la compilación. Así que pudimos obtener el valor de un. Pero este enfoque de declaración de variables no se recomienda ya que deberíamos declarar variables al principio así.

 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 no estará definido

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 variable, solo los polipastos de definición de variable, no la asignación.

  1. Elevación de declaración de función

A diferencia de la variable izar, 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 que entendimos tanto la elevación de variables como de funciones, entendamos este código ahora.

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

Este código resultará 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á alcance local dentro de b (). a () se moverá a la parte superior mientras se interpreta el código con su definición (solo en el caso de la función de elevación), por lo que ahora tendrá un alcance local y, por lo tanto, no afectará el alcance global de a mientras tiene su propio alcance dentro de la función b () .


0

Según mi conocimiento, el izado ocurre con la declaración de variable y la declaración de función, por ejemplo:

a = 7;
var a;
console.log(a) 

Qué sucede dentro del motor de JavaScript:

var a;
a = 7;
console.log(a);
// 7

O:

console.log(square(7)); // Output: 49
function square(n) { return n * n; }

Se convertirá:

function square(n) { return n * n; }
console.log(square(7)); // 49

Pero las asignaciones como la asignación de variables, la asignación de expresión de función no se elevarán: Por ejemplo:

console.log(x);
var x = 7; // undefined

Puede volverse así:

var x;
console.log(x); // undefined
x = 7;

0

Para describir el alojamiento en javascript en una oración, las variables y las funciones se colocan en la parte superior del alcance en el que se declaran.

ingrese la descripción de la imagen aquí

Supongo que es un principiante, para comprender el izado correctamente al principio, hemos entendido la diferencia entre undefined y ReferenceError

 var v;
 console.log(v);
 console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/

ahora en el código de abajo lo que vemos? una variable y una expresión de función se descuenta.

<script>
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
</script>

pero la imagen real con prueba de que tanto la variable como la función están en la parte superior de su alcance:

console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));

La salida de los dos primeros registros no está definida y TypeError: getSum no es una función porque tanto var totalAmo como getSum se colocan en la parte superior de su alcance como abajo

 <script>
        var totalAmo;
        var getSum;

        console.log(totalAmo);
        console.log(getSum(8,9));
        var totalAmo = 8;
        var getSum = function(a, b){
            return a+b;
        }
        console.log(totalAmo);
        console.log(getSum(9,7));
    </script>

Pero para la declaración de funciones, funciones completas se alzan en la parte superior de su alcance.

console.log(getId());
function getId(){
   return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/

Ahora la misma lógica se aplica a esas variables, experesiones de funciones y declaratoins de funciones declarados dentro del alcance funcional. Punto clave: no se izarán en la parte superior del archivo ;

function functionScope(){
            var totalAmo;
            var getSum;

            console.log(totalAmo);
            console.log(getSum(8,9));
            var totalAmo = 8;
            var getSum = function(a, b){
                return a+b;
            }
        }

Entonces, cuando usa la palabra clave var , variable y función en la parte superior de su alcance (alcance global y alcance de función). ¿Qué pasa con let y const? , const y let todavía son conscientes del alcance global y el alcance de la función al igual que var, pero las variables const y let también son conscientes de otro alcance llamado alcance bloqueado? un alcance de bloque está presente siempre que hay un bloque de código, como el bucle for, la declaración if else, el bucle while, etc.

Cuando usamos const y let para declarar una variable en el alcance de estos bloques, la declaración de la variable solo se elevará en la parte superior del bloque en el que se encuentra, y no se elevará en la parte superior de la función padre o en la parte superior de la alcance global que se iza.

 function getTotal(){
            let total=0;
            for(var i = 0; i<10; i++){
                let valueToAdd = i;
                var multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

Las variables en el ejemplo anterior se elevarán como abajo

 function getTotal(){
            let total;
            var multiplier;
            total = 0;
            for(var i = 0; i<10; i++){
                let valueToAdd;
                valueToAdd = i;
                multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

0

ES5: función de elevación y elevación variable

function hoistingla prioridad es greaterquevariable hoisting

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2016-06-01
 * @modified
 *
 * @description function-hoisting.js
 * @augments
 * @example
 * @link
 *
 */

(function() {
  const log = console.log;

  var a = 1;
  function b() {
    a = 10;
    log(`local a`, a)
    return;
    // function hoisting priority is greater than variable hoisting
    function a() {}
  }
  b();
  log(`global a`, a);
  // local a 10
  // global a 1
})();



que es igual a

(function() {
  const log = console.log;

  // define "a" in global scope
  var a = 1;
  function b() {
    // define "a" in local scope
    var a ;
    // assign function to a
    a = function () {};
    // overwrites local variable "a"
    a = 10;
    log(`local a`, a);
    return;
  }

  b();
  // log global variable "a"
  log(`global a`, a);

  // local a 10
  // global a 1
})();

la razón detrás de izar

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

/**
 *  scpope & closure & hoisting (var/function)
 *  
 * 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
 * Note: if a local variable not using var keywords in a function, it will become a global variable!
 * 
 * 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
 * 
 * 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
 * Note: it just move the declare, not move the value!
 * 
 */

ES6 let, constno existe elevación

(() => {
  const log = console.log;
  log(a)
  // Error: Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 1;
})();



(() => {
  const log = console.log;
  log(b)
  // Error: Uncaught ReferenceError: Cannot access 'b' before initialization
  const b = 1;
})();

refs

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.