Izar en JavaScript

En este artículo, aprenderemos sobre los efectos del levantamiento: cuando JavaScript coloca declaraciones de variables, funciones y clases en la memoria antes de la ejecución.

Introducción

Elevar es un comportamiento de JavaScript comúnmente conocido por hacer que las variables y funciones estén disponibles para su uso antes de que se asigne un valor a la variable o se defina la función. En efecto, coloca las declaraciones de variables, funciones y clases en la parte superior de su alcance (el alcance global o una función) antes de la ejecución.

En realidad, JavaScript no mueve ni agrega código a las declaraciones de elevación. Estas declaraciones se colocan en la memoria durante la fase de compilación del intérprete, lo que las hace disponibles antes de que se ejecute el código.

En este artículo, aprenderemos sobre la elevación y cómo afecta las variables, funciones y clases.

Variables de elevación

Uno de los aspectos clave de la elevación es que la declaración se guarda en la memoria, no el valor.

Veamos un ejemplo:

1
2
3
console.log(name); // Prints undefined, as only declaration was hoisted
var name = "John";
console.log(name); // Prints "John" 

Esto sucede porque JavaScript ve que tenemos un ’nombre’ de variable en el alcance y lo guarda en la memoria. A las variables declaradas con var se les da un valor de undefined hasta que se les asigna algo más.

Elevación variable con let y const

Los desarrolladores de JavaScript rara vez usan var en favor de las palabras clave let y const introducidas en ECMAScript 2015 (comúnmente conocido como ES6). Las variables declaradas con let y const se elevan. Sin embargo, no se inicializan con undefined ni con ningún valor. Por lo tanto, si se usan antes de inicializarse, obtendremos un ReferenceError.

Reutilicemos el mismo ejemplo, pero use let en lugar de var:

1
2
3
console.log(name); // Uncaught ReferenceError: Cannot access 'name' before initialization
let name = "John";
console.log(name);

El código anterior arroja un ReferenceError en la primera línea y finaliza la ejecución.

La palabra clave const se agregó para introducir valores inmutables en JavaScript, valores que no se pueden cambiar después de inicializarse. Como tal, cuando usamos const debemos declarar y asignar un valor a la variable. Si no lo hacemos, obtendremos un SyntaxError:

1
2
console.log(name); // Uncaught SyntaxError: Missing initializer in const declaration
const name;

Y como let, obtenemos un ReferenceError cuando tratamos de usar una constante antes de que se inicialice:

1
2
3
console.log(name); // Uncaught ReferenceError: Cannot access 'name' before initialization
const name = "John";
console.log(name);

Funciones de elevación {#funciones de elevación}

Las declaraciones de funciones se elevan en JavaScript. La declaración de una función comienza con la palabra clave función, seguida de su nombre y argumentos entre paréntesis, y luego su cuerpo. Consideremos el siguiente código:

1
2
3
4
5
6
7
8
9
let first_name = "Stack";
let last_name = "Abuse";

let result = concat(first_name, last_name);
console.log(result); // wikihtp

function concat(x, y) {
    return x + y;
}

Al igual que con las variables, JavaScript coloca la función en la memoria antes de ejecutar el código en ese ámbito. Por lo tanto, hoisting nos permite llamar a la función concat() antes de que se defina más adelante en el código.

Si bien las declaraciones de funciones se elevan, las expresiones de funciones no funcionan de la misma manera. Una expresión de función es cuando asignamos una variable a una función. Por ejemplo, el siguiente código devolverá un error:

1
2
3
4
5
func_express(); // TypeError: func_express is not a function

var func_express = function () {
    console.log('This the function expression is not a function');
};

JavaScript devuelve un TypeError porque, a diferencia de la declaración de la función, solo se elevó la variable. Cuando las variables declaradas con var se elevan, se les da un valor predeterminado de undefined. Entonces, JavaScript arroja un error porque el valor de la variable no es una función en ese momento.

Función Elevación con funciones de flecha

ECMA2015 introdujo una nueva forma de crear funciones anónimas, funciones de flecha. Estos están definidos por un par de corchetes que contienen 0 o más argumentos, una flecha => y el cuerpo de la función entre llaves. Con respecto a la elevación, operan como expresa otra función. Por ejemplo:

1
2
3
4
5
arrow_func_express(); // TypeError: arrow_func_express is not a function

var arrow_func_express = () => {
    console.log('This the arrow function is not a function');
};

Cuando usamos funciones de flecha, o cualquier otra expresión de función, siempre debemos definir la función antes de usarla en nuestro código. Esta es la forma correcta de usar una expresión de función:

1
2
3
4
5
let arrow_func_express = () => {
    console.log('This function expression will work');
};

arrow_func_express(); // This function expression will work

Clases de elevación

Las declaraciones de clase se elevan en JavaScript. Una declaración de clase no se inicializa cuando se eleva. Eso significa que, si bien JavaScript puede encontrar la referencia de una clase que creamos, no puede usar la clase antes de que se defina en el código.

Tomemos el siguiente ejemplo que arroja un error al intentar acceder a una clase antes de su definición:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var person = new Person();
person.name = "Jane";
person.age = 25;

console.log(person); // Uncaught ReferenceError: Cannot access 'Person' before initialization"

class Person {
    constructor(name, age) {
      this.name = name; this.age = age;
    }
}

El ReferenceError es similar a lo que sucede cuando intentamos acceder a una variable declarada con let o const antes de que se inicialice en nuestro script.

Las expresiones de clase, donde asignamos una definición de clase a una variable, se comportan de manera similar a las expresiones de función. Se izan sus declaraciones pero no su valor asignado.

Tomemos nuestro ejemplo anterior y usemos una expresión de clase en su lugar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var person = new Person();
person.name = "Jane";
person.age = 25;

console.log(person); // Uncaught TypeError: Person is not a constructor"

var Person = class {
    constructor(name, age) {
      this.name = name;
      this.age = age;
    }
}

Cuando se iza la variable ‘Persona’, se le asigna el valor ‘indefinido’. Como no podemos usar un valor indefinido como clase, JavaScript lanza un TypeError.

Al trabajar con declaraciones de clase o expresiones de clase, siempre debemos definir la clase antes en nuestro código para usarla. La forma correcta de usar una clase es la siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Person {
    constructor(name, age) {
      this.name = name; this.age = age;
    }
}

var person = new Person();
person.name = "Jane";
person.age = 25;

console.log(stack); // Person { name: 'Jane', age: 25 }

Conclusión

Polipastos de JavaScript, declaraciones de variables, funciones y clases. Ese artículo ha mostrado los impactos que tiene la elevación en la forma en que escribimos el código JavaScript.

Las declaraciones de funciones se pueden usar antes de su definición debido a la elevación. Sin embargo, para minimizar nuestras posibilidades de obtener valores “indefinidos”, así como errores de tipo o de referencia, es más seguro usar variables, expresiones de funciones y clases después de que estén definidas en nuestro código.