Javascript: Escribiendo buen código

viernes, 19 de julio de 2013


Ya sea porque recién comenzamos o porque necesitamos garantizar la efectividad de nuestros javascript, es necesario conocer que herramientas tenemos al alcance de la mano que nos ayuden a escribir buen código: quizás hayan leído o escuchado acerca de JsLint y JsHint, hoy vamos a hablar de ellos

Sin entrar en mucho detalle, ambas son herramientas que nos van a permitir validar nuestro javascript y asegurarnos que cumpla con determinadas reglas. En el caso de JsLint es un poco restrictivo acerca de su configuración y JsHint es un fork del anterior muchisimo más pulido, flexible y hecho por y para desarrolladores.

Con respecto a las reglas, podemos decirle a los validadores que tengan en cuenta aspectos como los siguientes y nos alerte al respecto:

  • Si tenemos variables que declaramos y no usamos
  • Si no usamos algún parámetro en una función
  • Comentarios del estilo TODO
  • Existencia de sentencias de debugging (console.log)
  • Comparaciones con == o != (No estríctas)
  • Cuando no usamos { } para separar bloques if (Por más que tengan una sola línea)
  • Si usamos funciones dentro de ciclos
  • Etcétera

En el sitio de JsHint, hay un apartado partícular que nos enseña como incluirlo para que sean de utilidad en nuestros proyectos. Hay muchas implementaciones y se encuentra en los entornos de desarrollo más utilizados

Casos que analizamos

  • Constructores

 var cat = new Object();
    cat.name = "Nacho";
    console.log(cat.name);

En este caso, las herramientas nos recomiendan que la notación literal de objetos es más adecuada

 var dog = {
        name: "Benji",
        getName: function () {
         return this.name;
  }
   };
    
    console.log(dog.getName());

Ventajas: Menos código, más claro a simple vista, menos repetitivo si debemos agregar propiedades y funcionalidad

  • Comparaciones

var a = 1, b = 2;

if (a = b) { 
  console.log(1);
} 
else { 
  console.log(2);
}
Javascript no espera que ocurran asignaciones dentro de bloques condicionales. Es más probable que la verdadera interpretación deseada sea if (a == b) o if (a === b)

Ambas herramientas alertarán al respecto y es configurable bajo la característica: "About assignments inside if/for/..."

  • Comparaciones de tipo al usar == y !=

  var gato = {edad:2};
   var perro = {edad:2};

   if(gato.edad == perro.edad){
    console.log("iguales");
   }
   else{
    console.log("diferentes");
   }

   // Muestra iguales

   perro.edad = "2"; // Convertimos el valor 2 en un string que tiene un 2

   if(gato.edad == perro.edad){
    console.log("iguales");
   }
   else{
    console.log("diferentes");
   }

   // Muestra "iguales". Porque Javascript internamente está haciendo una conversión de tipos              
   // para que ambos valores sean comparables. Entonces 2 será igual que "2"

   if(gato.edad === perro.edad){     // Comparamos estrictamente: Valor y tipo
    console.log("iguales");
   }
   else{
    console.log("diferentes");
   }

   // Muestra diferentes

   perro.edad = 2.0; // Asigno un valor con decimales

   if(gato.edad === perro.edad){
    console.log("iguales");
   }
   else{
    console.log("diferentes");
   }
   // Muestra iguales. Por qué? Porque Javascript no reconoce "subtipos", ambos son  
   // numéricos y por ende iguales
 
Ambas herramientas permiten configurar si nos alerta o no en caso de no usar comparaciones estrictas

  • Cuidado con la coma

    var json = {
       hola: "hola",
       como: "como",
       estas: "estas",
       numero: 1,          // La última coma no es necesaria, pero generalmente no muestra error
   };
La coma ubicada en algunos lugares de nuestro código sin ningún propósito puede generar errores en algunos navegadores. JsLint alerta siempre en este caso

  • ++ y --

JsLint posee la capacidad de no permitir dichos operadores argumentando que es una práctica que alienta astucia innecesaria y hace trabajar de más al compilador

   var num = 2;
   console.log(++num);     //3
   console.log(num++);     //3
El código anterior no valida, en JsHint si lo hace

Donde realmente creo que tenemos un problema es en los ciclos, por ejemplo, el siguiente código no es válido

   for (var i = 0; i < 10; i++) {
           console.log(i);
   }

Primero, porque especifica que las variables deben estar antes de bloques de código, quedando así

     var i;

   for (i = 0; i < 10; i++) {
       console.log(i);
   }
Y segundo por el ++ del incremento final. Esta regla no es muy útil creo, JsHint la conoce y no genera error.

  • Salto de linea


¿Cual es la diferencia entre las siguientes funciones?

function sayHello(){
 return {
  a:'hola'
 }; 
}

function sayHelloAgain(){
 return
 {a:'hola'}; 
}

A simple vista parecería que son iguales, la diferencia reside simplemente en el salto de linea del return ¿Pero acaso esto podría ocasionar algún problema? Si recordamos que en javascript el salto de linea es interpretado como el fin de una sentencia podemos inferir que la función no va a retornar lo que esperamos. En otras palabras return va a ser interpretado como una sola sentencia y el resultado de hacer sayHelloAgain() va a ser undefined ¿Que macana no? Afortunadamente tanto JsLint como JsHint nos pueden ayudar a evitar este tipo de errores. En este caso en particular lanzando una advertencia por el salto de linea o también de ausencia del punto y coma (dependiendo que reglas hayamos elegido).

En resumen, dada las ambigüedades de javascript contar con una herramienta amiga que nos ayude a no caer en ciertos errores es de gran utilidad (sobre todo por los dolores de cabeza que nos ahorramos). Si desean probar algunas de las validaciones sin instalar nada pueden hacerlo desde las respectivas paginas oficiales  de JsLint y JsHint.

Ir a JsLint
Ir a JsHint