Inicie correctamente sus desarrollos
Elegir su entorno de desarrollo
1. Introducción
Al carecer durante mucho tiempo de un IDE (Integraded Development Environment, Entorno de desarrollo integrado) o depender de un editor de texto simple, los desarrolladores web se han centrado en los asistentes de páginas HTML/CSS, olvidándose de JavaScript. La evolución del lenguaje ha hecho que pasemos de un uso más bien marginal a un uso masivo, especialmente con la llegada del móvil y HTML 5. Muchos editores de software se han adaptado y ahora ofrecen entornos completos. Por supuesto, siempre es posible usar un editor de texto generalista (como Notepad ++, vi, Emacs, etc.) y trabajar con él, pero a menudo esto implica privarse de asistentes de gran valor específicos para JavaScript, que aportan una ganancia real de tiempo en su trabajo.
Estos son algunos puntos esenciales que debe manejar un IDE de JavaScript:
-
Gestión de codificación (UTF-8, ISO-8859-1 como mínimo).
-
Coloración sintáctica.
-
Comprobación de sintaxis en tiempo real.
-
Asistentes de entrada de datos.
-
Refactorización.
-
Formateo de código.
-
Gestión de proyectos.
Al crear un archivo JavaScript, es mejor utilizar la codificación portable UTF-8. Este tipo de codificación Unicode puede contener una secuencia de caracteres al comienzo del archivo llamada BOM (Byte Order Mark), que está ahí para indicar el orden de los bytes, aunque también se usa para identificar la codificación Unicode UTF-8, UTF 16 o UTF-32. Quizás sea mejor no usar esta marca, ya que no todos los editores/herramientas la admiten.
La coloración y la verificación sintáctica están relacionadas. El ahorro de tiempo puede ser significativo debido al uso de paréntesis y llaves en JavaScript. El anidamiento de funciones y objetos puede hacer la sintaxis difícilmente legible. Tener una alerta instantánea mientras se está escribiendo el código, es un valioso ahorro de tiempo que le evitará esperar a la etapa de ejecución y la interpretación del mensaje de error en un navegador.
Un asistente de entrada puede ser útil para encontrar una variable, una función, etc., pero también para inspeccionar el contenido de un objeto. Esta última etapa estará presente para los objetos predefinidos...
Organizar su código
1. Separar el código de la presentación
En un uso Web, es más legible evitar cualquier mezcla de código entre la parte de presentación y la parte de procesamiento. El objetivo es mantener ambas lo más simples posible, reduciendo los efectos secundarios.
A continuación, se mostrará un ejemplo no muy correcto, que muestra la fecha cuando se visualiza la página (para más información, el atributo type de la etiqueta script ya no es indispensable en HTML5).
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Hola</h1>
<script type="text/javascript">
document.writeln( "Es " + new Date() );
</script>
</body>
</html>
El código JavaScript está en la etiqueta body, lo que generalmente no es una buena idea. El uso de document.writeln se debería prohibir en la medida de lo posible, porque solo interviene cuando el navegador interpreta la etiqueta script, lo que obliga a que el código se coloque en una ubicación exacta, y esto provoca una mezcla inevitable entre el código de presentación y el de procesamiento.
Por tanto, este código no es muy fácil de mantener. Para mejorar este aspecto, primero es posible mover el script hasta la etiqueta head de la página. Por supuesto, al hacer esto, ya no podemos usar writeln (este método escribe en el flujo de la página que se está cargando y la etiqueta head no es una etiqueta con contenido visible para el usuario final) y es necesario actualizar el contenido de la página en el momento de su carga completa, con el fin de determinar la zona que contendrá el resultado del código. La etiqueta body se convierte en una especie de plantilla de página. El uso del API DOM le permite agregar el resultado (ver el capítulo dedicado al desarrollo web). El evento onload en la página...
Ámbito de las variables y funciones
1. Ámbito de las variables
Cuando declara una variable, esta solo es "accesible" en ciertos lugares. Cuando su variable se declara fuera de cualquier función, se dice que su alcance es global, por lo que está disponible en todas las partes de su código.
a = 10;
function test() {
alert( a );
}
test();
En el ejemplo, hemos inicializado una variable a en 10. Se declara implícitamente en el momento de su uso. Al estar fuera de cualquier función, su alcance es global.
Ahora suponga que escribimos:
function test() {
a = 10;
}
test();
alert( a );
Ahora hemos inicializado la variable a en la función tests. Dado que tenemos una declaración implícita, habríamos esperado que a ya no fuera global. Sin embargo, es exactamente lo contrario. De hecho, la variable a declarada en la función test es global por defecto y podemos mostrar su valor fuera de la función test.
Esto no es aceptable porque podríamos corromper la ejecución de nuestras funciones si se usa el mismo nombre de variable.
Para evitar este tipo de inconvenientes, tenemos la palabra clave var. Esta última va a servir para declarar la variable, respetando el contexto actual. Por lo tanto, cuando se usa en una función, el alcance de la variable...
Optimización del ámbito
1. Limitar el contexto global
Las declaraciones en el contexto global no son recomendables en términos de calidad, pero tampoco en términos de rendimiento.
Con respecto a la calidad, cuantas más declaraciones tenga en el espacio de nombres global, más probabilidades tendrá de tener un conflicto al cambiar una variable por error. Este tipo de conflicto puede surgir de varias maneras: ya sea porque su código ha crecido cada vez más y ya no puede controlar todas sus declaraciones, o porque está agregando nuevas librerías.
En cuanto al rendimiento, leer una variable local es aproximadamente dos veces más rápido que leer una variable global. La razón es que el intérprete de JavaScript siempre prueba primero el contexto local, antes de mirar el contexto global. Por lo tanto, leer una variable global equivale a realizar una prueba adicional para el intérprete.
En el siguiente ejemplo, hemos creado dos bucles que realizan un cálculo simple, uno usando el contexto global y el otro usando el contexto local. Luego medimos la diferencia en la ejecución en milisegundos.
var i = 0;
var j = 0;
// Versión global
var test1 = function() {
for ( i = 0; i < 1000000; i++ ) {
j += j;
}
}
// Versión local
var test2 = function() {
var j = 0;
for ( var i = 0; i < 1000000; i++ ) { ...
Simplificar sus expresiones
1. El operador ||
Conoce el operador booleano ||. Este operador realiza un "o lógico ", pero también tiene la particularidad de devolver el primer valor evaluado como verdadero (true). En JavaScript, un valor es implícitamente verdadero si es diferente de false, undefined, 0, null y "" y viceversa para un valor falso.
Ejemplo:
var a = null;
var b = a || 10;
alert( b );
En nuestro ejemplo, hemos inicializado la variable a a null (por lo tanto, implícitamente a falso), la variable b recibe el último valor que es verdadero, es decir el valor 10.
Por lo tanto, el operador || se puede utilizar para garantizar un valor de manera práctica.
function test( a ) {
a = a || 10;
alert( a );
}
test();
test( 11 );
En este ejemplo, tenemos un parámetro a que se puede indicar o no; si no es así, obtendrá automáticamente el valor 10 por defecto. Por tanto, en la pantalla tendremos 10 durante una llamada sin parámetros y 11 durante una llamada con el parámetro.
También es posible tener un parámetro que contenga un conjunto de propiedades parcialmente presentes.
function action( config ) {
var defConfig = {
color: "blue",
font: "arial"
};
config = config || defConfig;
var color = config.color || defConfig.color;
var font = config.font || defConfig.font;
alert( color + " y " + font );
}
action();
action( { color: "red" } );
action( { color: "red", font: "times" } );
En la función action, tenemos un parámetro opcional config, que contiene parte o la totalidad de las propiedades color y font. Gracias al operador ||, siempre tenemos un valor para cada propiedad, acudiendo si es necesario a un objeto predeterminado (defConfig).
El operador || es ciertamente práctico, pero se debe usar con prudencia.
A continuación, se muestra un contra ejemplo:
function test( a ) {
a...
Paso al modo strict
1. Uso
El modo strict es una novedad en el estándar ECMAScript 5 (compatible con Firefox 4+, Internet Explorer 9+, Safari 5.1+, Opera 11.6+, Chrome 13.0+), es una forma de mejorar la calidad de su código a un coste menor. También sirve para facilitar la transición a futuras versiones de JavaScript.
Este modo se activa en la parte superior de su código o sus funciones, con la siguiente cadena:
"use strict";
Le dice a su navegador que ya no autoriza ciertos códigos y que se debe generar un error de sintaxis cuando se detecten. Observe que colocar esta cadena al principio de su código o funciones es perfectamente compatible con los navegadores que no admiten este modo (una cadena es una expresión que no provoca nada).
Ejemplo de una función en modo strict:
<html>
<head>
<script type="text/javascript">
function test() {
"use strict";
aa = 10;
}
test();
</script>
</head>
<body>
</body> ...
JSHint
1. Uso básico
JSHint (http://www.jshint.com) es una librería de JavaScript basada en JSLint (un proyecto similar). Su propósito es analizar su código y hacerle saber si se pueden realizar mejoras. Esto no se refiere necesariamente a los errores en sí mismos. Se trata más del control de calidad del código, como la sangría, el paso sistemático al modo strict, etc.
Básicamente, JSHint funciona gracias a una función global JSHINT que recibe tres argumentos:
-
Su código fuente de JavaScript.
-
Un conjunto de opciones que le dicen a JSHint qué verificar en el código, como verificar bloques vacíos, sangría, convención de nomenclatura, etc.
-
Un conjunto de variables globales no obligatorias con un "flag" (booleano), para indicar si se pueden modificar.
Si el código que pasa es correcto, la función devuelve verdadero; de lo contrario, se devuelve falso.
En caso de errores, aparece una tabla de errores con JSHint.errors. Consiste en un conjunto de objetos de error, que incluyen la ubicación del error y la causa.
A continuación, se muestra un ejemplo bastante simple que consiste en verificar si hay bloques vacíos en el código con la opción noempty. Primero necesitamos descargar e instalar el script jshint.js.
<html>
<head>
<title>Test JSHint</title>
<script type="text/javascript" src="jshint.js"></script>
<script type="text/javascript">
var result = JSHINT( "a = 10;\nif ( a == 10 ) {}",
{noempty:true} );
var errors = JSHINT.errors;
if ( errors.length > 0 ) {
for ( var i = 0; i < errors.length; i++ ) {
var error = errors[ i ];
var linea = error.line;
var...
Documentar su código con JSDoc
1. El principio
JSDoc utiliza el concepto de JavaDoc de Java y de las anotaciones. Consiste en incorporar marcadores en sus comentarios. Gracias a estos marcadores, es posible generar documentación más legible, mientras se refuerzan ciertos controles. Herramientas adicionales pueden comprender mejor su código, para realizar un procesamiento de tipo de compresión con Google’s Closure. Finalmente, algunos editores de software como WebStorm y NetBeans pueden interpretar sus marcadores y ayudarlo mejor con la entrada de datos.
También podemos decir que JSDoc es, de alguna manera, una extensión de JavaScript en términos de tipado para identificar mejor los valores utilizados.
Para utilizar JSDoc, sus comentarios deben tener el siguiente formato:
/**
Sus comentarios
*/
Preste atención y no olvide la doble estrella al inicio del comentario.
Un marcador comienza con @, por ejemplo, @param designará un parámetro de función.
2. Los marcadores
a. Declaraciones
El caso más simple es el uso del marcador type para designar la naturaleza de una variable o la naturaleza del valor devuelto por una función:
/** @type {Number} */
var a = 10;
/** @type {String} */
var miCadena = "hello world";
/** @type {Boolean} */
var estado = true;
/** @type {Boolean} */
function flag() {
return "ok";
}
Gracias al marcador constant, tiene la posibilidad de indicar que una variable es, en realidad, una constante:
/** @constant */
var c = 10;
c++; // Error de edición porque c no se puede modificar
b. Funciones
Para documentar una función, en general dispondrá del uso de @param y @return:
/**
* Realizar una operación binaria
* @param {Number} operando1 Un entero
* @param {Number} operando2 Un entero
* @param {String} operador Una cadena que designa la operación
* @return {Number} el resultado de la operación
*/
function calculo( operando1, operando2, operador ) {
return eval( operando1 + " " + operador + " " + operando2...
Paso de un entorno de desarrollo a un entorno de producción
1. Pruebas unitarias
a. Introducción
Cuando su código es estable y tiene funciones y/o clases críticas, puede ser conveniente implementar pruebas unitarias para validar su funcionamiento. Esto es aún más importante si tiene que realizar actualizaciones para reducir los problemas de regresión, al pasar a un entorno de producción.
Desde un punto de vista práctico, es mucho más fácil implementar pruebas unitarias que sus funciones y/o clases a probar estén presentes en archivos JavaScript independientes de sus páginas HTML.
La forma más sencilla de realizar pruebas unitarias es evaluar un conjunto de expresiones y validar que el resultado coincida con un resultado dado. De lo contrario, la prueba unitaria falla y el paso a producción se debe retrasar hasta que se resuelva el problema.
b. Gestión con su propia librería
Implementar su propio sistema de pruebas unitarias no tiene por qué ser muy complicado. Depende principalmente de cómo se haya estructurado su código. Por ejemplo, puede crear tantas páginas HTML de prueba como scripts tenga.
Considere un ejemplo simple con un conjunto de funciones de calculo. Suponemos que estas funciones están presentes en un archivo calculo.js independiente. Podemos tener este tipo de estructura en su interior:
/*
* Módulo de cálculo
*/
var calculo = ( function() {
var calculo = {};
function division( a, b ) {
return a / b;
}
function suma( a, b ) {
return a + b;
}
calculo.division = division;
calculo.suma = suma;
return calculo;
} )();
Tenemos dos funciones division y suma que están disponibles mediante el objeto calculo. Si no entiende esta organización, puede consultar el capítulo dedicado a las buenas prácticas. Solo recuerde que hemos ocultado el acceso directo a las funciones division y suma (están...