CPJS: Scope

El Scope o ámbito es lo que define el tiempo de vida de una variable, en qué partes de nuestro código pueden ser usadas.

Scope

Scope o ámbito de una variable representa el tiempo de vida en el que esta existe, puede ser una variable que hayamos definido o el argumento a un función. Eso es muy importante por que evite que reescribamos el valor de una variable que ya habíamos definido. Por desgracia JavaScript no siempre tuve el mejor sistema de scope de variables, en el libro JavaScript: The Good Parts de Douglas Crockford se dice que el scope y variables globales son de las cosas más horrible que tiene el lenguaje. Por suerte esto a mejorado muchísimo, ahora tenemos a let y const que nos ayuda a evitar estos problemas.


Scope global

Vamos a hacer algunas pruebas en el código para experimentar con estas variables.

Si declaramos un var de la siguiente forma lo estaríamos haciendo globalmente.

1 var message = "¡Hello, Soter!";

Si vamos a la consola y escribimos windows.message no da el mensaje que guardamos en la consola. Windows es nuestro ámbito global.

Si agregamos una CDN externo como jQuery podremos acceder a ese código globalmente. El peligro está en cambiar alguna característica del CDN global que trajimos.

1 var message = "¡Hello, Soter!";
2 var $ = function(message) {
3 console.log("Say: " + message);
4}

Si escribimos en la consola lo siguiente nos dará el resultado...

1 $('Hola')
2// Say: Hola

Vimos que cambiamos por completo el acceso a elementos de jQuery, pero también nos dimos cuenta de que el message no era: ¡Hello, Soter! si no Hola, a esto se le llama: Scope definition.


Ahora hagamos otro ejemplo,una función que imprimirá números.

1 function printNumbers(params) {
2 for (var i = 0; i < 10; i++) {
3 setTimeout(() => {
4 console.log(i)
5 }, 100);
6 }
7 }
8
9 printNumbers()

Crea un ciclo de 10 número del 0 al 9 y va a tener un retardo de 100ms, pero si ejecutamos este código pasa algo extraño:

1 // (10) 10

Se imprime 10 veces 10 y eso no es lo que queremos.

Esto pasa por function scope, algo pasa con la variables var, pasa que el lenguaje lo declara como variable global y cuando llega el turno de imprimir el valor de i resulta que ya tiene 10. Se soluciona llamando a una función en el ciclo que ejecute el setTimeOut.

1 function printNumbers(params) {
2 for (var i = 0; i < 10; i++) {
3 function eventuallyPrintNumbers(n) {
4 setTimeout(() => {
5 console.log(n)
6 }, 100);
7 }
8 eventuallyPrintNumbers(i)
9 }
10 }
11
12 printNumbers()

Haciéndolo así var conserva su valor real por cada ciclo. El valor i paso a un scope n totalmente nuevo.


Block scope

Con las nuevas actualizaciones tenemos acceso a una variable que trabaja en el bloque de ejecución, siempre recordando su valor.

1 function printNumbers(params) {
2 for (let i = 0; i < 10; i++) {
3 setTimeout(() => {
4 console.log(i);
5 }, 100);
6 }
7 }
8
9 printNumbers();


Module scope

Es probable que lo hayamos usado en Node o en React usando herramientas como Babel. Lo que hace es que el scope de esa variable se limite al archivo donde está definido.

1 script type="module" src="./assets/index.js"


El type="module" declara que el archivo es un módulo. Esto no está en todos los navegadores pero sí en los más modernos. Ya no podemos acceder a las variables globales de este archivo desde la consola.


Importar y exportar

Podemos separar código que esté en un archivo js usando export e import. En nuestro archivo ./assets/index.js separaremos el código que usar nuestro media player en otro archivo llamado MediaPlayer.


Nuestro archivo index.js tendrá:

1 import MediaPlayer from "./MediaPlayer.js";
2 const video = document.querySelector("video");
3 const button = document.querySelector("button");
4
5
6 const player = new MediaPlayer({ el:video });
7
8 button.onclick = () => player.play();


Y el archivo MediaPlayer.js:

1 function MediaPlayer(config) {
2 this.media = config.el;
3 }
4
5 MediaPlayer.prototype.play = function() {
6 // if(this.media.paused){
7 //this.media.play();
8 // } else {
9 // this.media.pause()
10 // }
11 // o podemos usar lo siguiente:
12 this.media.paused ? this.media.play() : this.media.pause();
13 };
14
15 export default MediaPlayer;


Si exportamos una variable del archivo importado, ejemplo: export const foo = "hi", entonces tendríamos que importarlo de la siguiente forma:


1 import MediaPlayer, { foo } from "./MediaPlayer.js";

Entre llaves.


El scope es el lugar de vida de una variable y nos evita sobrescribir el valor de esta. En JavaScript tenemos cuatro:

    1. Global scope: Variables disponibles de forma global se usa la palabra var, son accesibles por todos los scripts que se cargan en la página. Aquí hay mucho riesgo de sobreescritura
    2. Function scope: Variables declaradas dentro de una función sólo visibles dentro de ella misma (incluyendo los argumentos que se pasan a la función).
    3. Block scope: Variables definidas dentro de un bloque, por ejemplo variables declaradas dentro un loop while o for. Se usa let y const para declarar este tipo de variables.
    4. Module scope: cuándo se denota un script de tipo module con el atributo type="module las variables son limitadas al archivo en el que están declaradas.
Esto va a declarar que este archivo es un módulo. Esto no está en todos los navegadores pero sí en los más modernos. Los valores que teníamos escritos ahora no los vamos a poder leer en consola porque el module scope está limitando el alcance

No hay comentarios.:

Con tecnología de Blogger.