1. Libros y videos
  2. JavaScript
  3. Adoptar buenas prácticas
Extrait - JavaScript Desarrolle eficazmente (2ª edición)
Extractos del libro
JavaScript Desarrolle eficazmente (2ª edición) Volver a la página de compra del libro

Adoptar buenas prácticas

Espacio de nombres

1. Principio

Cuando desarrollemos, procuraremos no exponer un número excesivo de funciones o variables/constantes en el espacio de nombres global para evitar conflictos de nombres. Esto significa dar acceso solo a lo que es útil y ocultar todo lo demás. Es un poco como el principio de una caja negra con entradas y salidas bien definidas, pero cuya mecánica interna permanece oculta.

Esto cobra aún más importancia si el código puede utilizarse en otros contextos. El problema es que solemos añadir funciones a nuestros archivos sin tener en cuenta su reutilización. A medida que nuestro proyecto crece, se vuelve cada vez más difícil de mantener. Combinar dos fragmentos de código puede, entonces, provocar conflictos que no resultan evidentes a simple vista y el resultado de la ejecución se vuelve incierto.

Para limitar los conflictos de nombres, añadiremos un contexto adicional (una especie de supercontexto) que garantizará que nuestras funciones y variables/constantes no puedan ser alteradas ni utilizadas accidentalmente. Este espacio de nombres es una especie de contenedor de nombres. Un nombre solo tiene sentido en relación con su espacio de nombres. Por lo tanto, resulta imposible invocar una función que no se encuentre en el espacio de nombres esperado.

Dado que cada código tiene su propio espacio de nombres, ya no existe el riesgo de colisiones asociadas a un código que pertenezca a otro espacio.

Un espacio de nombres es una característica presente en muchos lenguajes. En Java, por ejemplo, la palabra clave package se utiliza para realizar la declaración, al igual que namespace en C#. En JavaScript, lamentablemente no disponemos de una palabra clave para este fin, pero contamos con otros trucos igualmente potentes para lograrlo.

Este principio es importante para la calidad de sus programas. Una vez que lo haya entendido, se convertirá en algo natural y su forma de desarrollar mejorará aún más.

Cuanto mayor sea su programa, más necesitará espacios de nombres. Es el tamaño de su proyecto lo que impone su uso. Tener en cuenta el espacio de nombres será, por tanto, garantía de un código de mejor calidad, que podrá evolucionar más fácilmente y con mayor seguridad y, por lo tanto, con menos regresiones...

Módulo

1. Presentación

El concepto de módulo se deriva de la estructura anterior. La idea es ofrecer un formato universal para los bloques de funcionalidad. Un módulo representa una parte independiente de nuestro código. Por ejemplo, podríamos tener un módulo encargado de un tipo de cálculo o un módulo que represente un componente gráfico. No hay que confundir un módulo con una función; está por encima de la función y oculta todas las funciones y propiedades útiles para ofrecer un servicio.

Anteriormente vimos que la función podía servir como espacio de nombres que protegía de conflictos ciertos métodos o variables/constantes de nuestro código. Esto nos ha llevado a diseñar nuestro módulo:

function miModulo() { 
   // Definición privada  
   variables ...  
   funciones ...  
 
   return { 
      // Definición pública  
      propiedades...  
      métodos...  
   }  
} 

Esta estructura se puede utilizar en cualquier parte e incluso sustituye a sus clases. También podremos devolver indistintamente un objeto único, un constructor o una función.

Si, por ejemplo, desea obtener varias instancias, necesita un constructor que se encargue de generar las instancias bajo demanda:

function miModulo {     
   // Definición privada  
   variables para todas las instancias...  
   funciones ...  
 
  // Constructor intermedio para cada instancia  
  return function() {   
    return {   
      // Definición pública     
      propiedades......

CommonJS

1. Presentación

Si queremos que un módulo sea más accesible, es decir, fácilmente utilizable por todos, debemos ajustarnos a un estándar; de ahí el uso de soluciones como las que propone CommonJS (http://www.commonjs.org/). CommonJS nació en 2009 impulsado por Kevin Dangoor con la idea de normalizar ciertas API de JavaScript. Como hemos visto hasta ahora, JavaScript ofrece una gran expresividad al programar, lo cual resulta agradable, pero también esconde un verdadero problema de normalización e interoperabilidad. Esta forma normalizada se retomó posteriormente para el proyecto Node.js.

2. exports

Como hemos visto anteriormente, un módulo con una función anónima devolverá un valor, una función, una clase, un objeto, etc. En CommonJS, este principio se ha estandarizado mediante la propiedad exports, accesible desde un objeto module asociado a cada archivo que representa un módulo. Todo lo que no esté asociado a la propiedad exports queda oculto (como si estuviera dentro de nuestra función anónima).

Si comparamos el uso de un módulo mediante una función anónima con el uso de un módulo CommonJS, tendríamos lo siguiente:

Módulo mediante función anónima:

exports =(function() {   
      .... Parte oculta   
return valor/función/clase/objeto...   
})() ;   
 ...

Módulos ES

1. Presentación

Los módulos ES (o ESM) son una forma estandarizada de módulos incorporada desde el estándar ES6. Se basan en dos principios: un archivo representa un módulo. En su interior, la parte visible del módulo se exporta (mediante export). El acceso a un módulo se realiza mediante la palabra clave import, especificando la referencia recibida del módulo (lo que se exporta) y la ruta al archivo del módulo en cuestión.

Los módulos ES son asíncronos, por lo que no provocan bloqueos en la ejecución.

2. export

El principio es el mismo que para los módulos CommonJS, pero export es una palabra clave y no una función o una propiedad de un objeto. Esta palabra clave export se puede utilizar en varios lugares. Por ejemplo, delante de una función, un objeto o una clase. Por lo tanto, con los módulos ES se pueden exportar varias cosas a la vez. A la hora de importar, solo hay que utilizar el mismo nombre que la parte exportada: por ejemplo, si se exporta una función test, habrá que importar también una función test.

Si exportamos una función calculo, tendremos este módulo:

// modulo3.js   
   
function suma(v1,v2) {   
    return v1 + v2;   
}   
    
function division(v1,v2) {   
    return v1 / v2;   
} 
  export function calculo(operador,v1,v2) { 
    switch(operador) {   
        case '+':   
           ...

Consola

1. Acceso

Como ya vimos en el primer capítulo, todos los navegadores recientes disponen de una consola JavaScript. Esta consola no sirve solo para los mensajes de error; es posible acceder a ella directamente desde su script.

He aquí una tabla con los atajos de teclado para acceder a la consola según su navegador. En versiones antiguas de Firefox se recomendaba instalar Firebug, pero actualmente sus funciones están integradas en las herramientas de desarrollo de Firefox.

Microsoft Edge

[Ctrl][Mayús] I o bien a través del submenú Más herramientas - Herramientas de desarrollo

Firefox Developer Edition

[F12]

Chrome

[Ctrl][Mayús] J o [F12]

Safari

[Cmd][Opción] I

Opera

[Ctrl][Mayús] I o [F12]

2. log

Para interactuar con la consola, hay disponible un objeto predefinido llamado console. Preste atención, ya que no es compatible con navegadores antiguos. El método log admite un número indeterminado de argumentos. Es necesario especificar correctamente la codificación de los caracteres antes de utilizarlo mediante la etiqueta meta.

Ejemplo

<!DOCTYPE html>  
 
<html>  
    <head>  
        <script>  
 
// Uso sencillo de la consola del navegador  
 
for ( let i = 10; i >= 0; i -- ) { 
    console.log( i );  
}  
 
</script>  
    </head>  
 
    <body>  
 
    </body> 
</html> 

Este es el resultado en Firefox Developer Edition tras activar la consola y actualizar la página:

images/JS-08.png

En Chrome:

images/JS-09.png

En Microsoft Edge tras actualizar:

images/JS-10.png

Si utiliza varios argumentos, se concatenarán y se separarán por un espacio para formar una nueva cadena.

Ejemplo

console.log( 1, 2, "test" ); 

Lo que se muestra en la consola:

1 2 test 

El método log también admite el formateo de tipo «printf».

Ejemplo

console.log( "test %d %s", 10, "ok" ); 

Con este resultado en la consola:

test 10 ok 

También se pueden observar las propiedades de un objeto. Existe una variante que utiliza el método dir con el objeto como argumento.

Ejemplo

console.dir( { apellido: "Brines", nombre: "Alejandro" }...