JSHint es una herramienta que nos puede ayudar a mejorar la calidad del código que escribamos.
Esta herramienta detecta errores y problemas potenciales en el código de JavaScript además de que se pueden ajustar a las convenciones de codificación de tu equipo de trabajo.
JSHint se puede utilizar directamente con node.js pero lo vamos a utilizar con grunt.
Para utilizar jshint en nuestro proyecto – una vez que instalamos grunt – seguimos el proceso utilizado con otros módulos.
- Instalar el módulo
- Incluir el módulo, definimos la tarea en el archivo Gruntfile.js
- Ajustar las preferencias de la tarea – dentro de Gruntfile.js –
Instalar el módulo
$ npm install grunt-contrib-jshint --save-dev
Una vez instalado el archivo package.json debe incluir la dependencia del módulo – grunt-contrib-jshint -.
{
"name": "demo",
"version": "0.1.0",
"private": "true",
"description": "Crear un paquete json para utilizar grunt",
"main": "index.html",
"author": "eamexicano",
"license": "MIT",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.10.0"
}
}
Incluir el módulo
En el archivo Gruntfile.js necesitamos:
- Incluir el módulo que tiene la tarea – jshint -.
- Registrar la tarea.
- Configurar la tarea.
module.exports = function(grunt) {
grunt.initConfig({
// 3. Configurar la tarea
jshint: {
}
});
// 1. Incluir el módulo
grunt.loadNpmTasks('grunt-contrib-jshint');
// 2. Registrar la tarea
grunt.registerTask("default", ['jshint']);
};
Incluir el módulo y registrar la tarea.
Configurar la tarea jshint
Las opciones de jshint son muchas. Se encuentran agrupadas en tres secciones generales:
- Forzar opciones – Enforcing Options -: Cuando alguna de estas opciones se establece como verdadera – true – esto hará que JSHint muestre más advertencias acerca de tu código.
- Relajar opciones – Relaxing Options -: Cuando alguna de estas opciones se establece como verdadera – true – esto hará que JSHint muestre menos advertencias acerca de tu código.
- Ambiente – Environment -: Estas opciones permiten especificar a JSHint que se van a utilizar algunas variables globales predefinidas.
Forzar Opciones
Algunas de las opciones de esta sección que podemos configurar son:
Opción |
Descripción |
bitwise |
Esta opción prohibe el uso de operadores de bit a bit como ^ (XOR), | (OR), & (AND), etc. |
curly |
Esta opción requiere que siempre se utilicen llaves {} alrededor de los bloques en ciclos y condicionales. |
eqeqeq |
Esta opción prohibe el uso de igualdad (==) y no igualdad (!=) para utilizar identidad === y no identidad (!==). |
es3 |
Esta opción indica que el código se necesita adherir a la especificación de ECMAScript 3. Útil si el código se va a ejecutar en navegadores antiguos – en especial Oldie – o en otro contexto de legado de JavaScript. |
freeze |
Esta opción prohibe que se sobrescriban – extiendan – prototipos de objetos nativos como Array, Date, entre otros. |
immed |
Esta opción prohibe el uso de IIFE sin envolverlas en paréntesis. El envolver la función en paréntesis ayuda a los lectores de código a entender que la expresión es el resultado de la función y no la función como tal. |
latedef |
Esta opción prohibe el uso de una variable antes de que fuera definida. |
quotmark |
Esta opción refuerza la consistencia en las comillas utilizadas en el código. |
undef |
Esta opción prohibe el uso explícito de variables no declaradas. |
Relajar opciones
Algunas de las opciones de esta sección que podemos configurar son:
Opción |
Descripción |
asi |
Esta opción elimina las advertencias acerca de puntos y comas faltantes – al terminar sentencias de javascript -. |
eqnull |
Esta opción elimina las advertencias acerca de comparar valores con null – == null -. Estas comparaciones pueden resultar útiles si se quiere revisar si una variable es null o undefined. |
esnext |
Esta opción le indica a JSHINT que tu código utiliza sintaxis de ECMAScript 6. |
evil |
Esta opción elimina las advertencias acerca del uso de eval. El uso de eval est desaconsejado porque hace que tu código sea vulnerable a distintos tipos de ataque, además de que hace más difícil que el intérprete de JavaScript lo pueda optimizar. |
Ambiente
Algunas de las opciones de esta sección que podemos configurar son:
Opción |
Descripción |
browser |
Esta opción define globales expuestas por los navegadores modernos como document, navigator incluyendo algunas de HTML5 como FileReader. |
devel |
Esta opción define globales que son utilizadas – generalmente – para depurar código: console, alert. Es buena idea no incluirlas en el código que se va a utilizar. |
nonstandard |
Esta opción define globales no estándares pero que son utilizadas como escape y unescape. |
worker |
Esta opción define globales disponibles cuando el código está siendo ejecutado dentro de un WebWorker. |
La lista completa de opciones se puede consultar en: http://jshint.com/docs/options/.
Dentro del objeto jshint vamos a definir los archivos que se van a evaluar y la manera en que van a ser evaluados.
Para definir los archivos a evaluar utilizamos la propiedad files y le asignamos un arreglo como valor. Dentro del arreglo se puede escribir el nombre de un archivo, de varios archivos separados por comas, podemos utilizar * que se sustituye por cualquier carácter.
jshint: {
files: ['js/demo.js'],
// files: ['js/*.js'],
// Si queremos evaluar todos los archivos .js
// que se encuentran dentro de la carpeta js
}
Después de definir los archivos, definimos las opciones de cómo queremos evaluar el código:
grunt.initConfig({
jshint: {
files: ['js/demo.js'],
options: {
// Prohibir use de operadores como ^, |, &
bitwise: true,
// Utilizar operadores de identidad === en lugar de operadores de igualdad ==
eqeqeq: true,
// Utilizar llaves para definir bloques de código
curly: true,
// No extender prototipos nativos
freeze: true,
// Elegir un tipo de comillas para el texto
quotmark: "double",
globals: {
// El código se va a utilizar en el navegador - DOM c / document -
browser: true,
// El código utiliza alert y console para enviar notificaciones
devel: true
}
}
}
});
En los archivos de código que había escrito no tenían ningún error – el código escrito era bastante simple y no tenía mucha funcionalidad -. Por eso modifiqué e incluí algunas lineas de código en demo.js. Estas líneas de código no cumplen con las evaluaciones definidas en las opciones.
String.prototype.snake_case = function () {
this.toLowerCase().replace(/ /gi, "_");
}
var titulo = document.getElementsByTagName("h1")[0];
function visualizar_contenido() {
mensaje = titulo.textContent;
if (mensaje == "prueba" | mensaje === 'test')
alert("Utiliza otro mensaje");
console.log(mensaje.snake_case());
}
titulo.addEventListener("click", visualizar_contenido);
var parrafo = document.getElementsByTagName("p")[0];
function actualizar_contenido() {
parrafo.textContent = prompt("¿Nuevo contenido para el párrafo?");
}
parrafo.addEventListener("click", actualizar_contenido);
Archivo a evaluar.
Para evaluar los archivos definidos con las opciones que definimos ejecutamos la tarea jshint.
$ grunt jshint
# Si definimos la tarea jshint como predeterminada
# podemos ejecutar simplemente
# $ grunt
En el caso de que existan líneas de código no cumplan con las opciones que definimos, se visualiza en la línea de comandos la ubicación del código que no cumple con las opciones junto con un mensaje describiendo qué es lo que no se cumple.
Corregimos el código para que cumpla con las especificaciones.
function snake_case (text) {
return text.toLowerCase().replace(/ /gi, "_");
}
var titulo = document.getElementsByTagName("h1")[0];
function visualizar_contenido() {
mensaje = titulo.textContent;
if (mensaje === "prueba" || mensaje === "test") {
alert("Utiliza otro mensaje");
}
console.log(snake_case(mensaje));
}
titulo.addEventListener("click", visualizar_contenido);
var parrafo = document.getElementsByTagName("p")[0];
function actualizar_contenido() {
parrafo.textContent = prompt("¿Nuevo contenido para el párrafo?");
}
parrafo.addEventListener("click", actualizar_contenido);
Evaluamos las modificaciones realizadas.
Aunque jshint nos puede ayudar a prevenir problemas potenciales, no sustituye la evaluación del código con librerías como jasmine o qUnit.
Puedes descargar el demo de jshint:
- demo-14: Dependencia de “grunt-contrib-jshint” en package.json
- demo-15: Configuración del archivo Gruntfile.js código mal escrito en demo.js
Para instalar las dependencias se teclea desde la carpeta del proyecto:
$ npm install