Terribles errores de JavaScript que se deben evitar con un analizador de código estático

 

 

 


Índice
  1. JSLint, JSHint y compilador de cierre
    1. JSLint
    2. JSHint
    3. Compilador de cierre
    4. Elegir el corrector adecuado
  2. == Contra ===
  3. Variables indefinidas y definiciones tardías
  4. Reutilización de variables
  5. Llaves en bloques, bucles y condicionales
  6. Comillas simples y dobles
  7. Complejidad ciclomática
  8. Verifica todo lo que editarás más de una vez
    1. Otras lecturas

Los analizadores estáticos analizan el código y encuentran problemas antes de ejecutarlo. Realizan comprobaciones simples, como hacer cumplir la sintaxis, y comprobaciones más holísticas, como asegurarse de que sus funciones no sean demasiado complejas. Los analizadores estáticos también encuentran errores que no se pueden encontrar con las pruebas, como casos en los que ==quisiste decir ===. En proyectos grandes y en equipos grandes, estará feliz de recibir un poco de ayuda para encontrar esos errores "simples" que resultan ser mucho menos simples de lo que parecen.

 

Casi ninguna línea de mi código sale perfecta la primera vez que la escribo. Bueno, la mayor parte del tiempo... Algunas veces... Um, casi nunca. La verdad es que paso más tiempo persiguiendo mis propios errores de programación estúpidos del que me gustaría admitir. Por eso utilizo analizadores estáticos en cada archivo JavaScript que escribo.

Los analizadores estáticos analizan el código y encuentran problemas antes de ejecutarlo. Realizan comprobaciones simples, como hacer cumplir la sintaxis (por ejemplo, tabulaciones en lugar de espacios) y comprobaciones más holísticas, como asegurarse de que sus funciones no sean demasiado complejas. Los analizadores estáticos también encuentran errores que no se pueden encontrar con las pruebas , como instancias en las ==que usted quiso decir ===.

 

En proyectos grandes y en equipos grandes, estará feliz de recibir un poco de ayuda para encontrar esos errores "simples" que resultan ser mucho menos simples de lo que parecen.

JSLint, JSHint y compilador de cierre

Tiene tres opciones principales para analizadores estáticos en el mundo de JavaScript: JSLint , JSHint y Closure Compiler .

JSLint

JSLint fue el primer analizador estático para JavaScript. Puede ejecutarlo en el sitio web oficial o utilizar uno de los contenedores para ejecutarlo en sus archivos locales. JSLint encuentra muchos errores útiles, pero es muy rígido. He aquí un buen ejemplo:

var s = 'mystring';for (var i = 0; i s.length; i++) { console.log(s.charAt(i));}

JSLint mostrará dos errores para este código:

Unexpected '++'.Move 'var' declarations to the top of the function.

El primer problema es la declaración de la variable ien la parte superior del bucle. A JSLint tampoco le gusta el ++operador al final de la declaración del bucle. Quiere que el código se vea así:

var s = 'mystring';var i;for (i = 0; i s.length; i = i + 1) { console.log(s.charAt(i));}

Aprecio de dónde viene JSLint, pero es demasiado estricto para mí. También era demasiado rígido para Anton Kovalyov , por lo que creó JSHint.

JSHint

JSHint funciona de manera similar a JSLint, pero está escrito sobre Node.js y es mucho más flexible. JSHint tiene una larga lista de opciones , lo que permite crear comprobaciones personalizadas escribiendo su propio reportero .

Puede ejecutar JSHint desde el sitio web , pero la mayoría de las veces instalará JSHint como una herramienta de línea de comandos local usando Node.js. Una vez que JSHint esté instalado, puede ejecutarlo en sus archivos con un comando como este:

jshint test.js

JSHint también tiene complementos para editores de texto populares, por lo que puede ejecutar JSHint mientras codifica.

Compilador de cierre

El compilador de cierre, de Google, es una raza diferente. Como sugiere el nombre, es tanto un compilador como un verificador. Está escrito en Java y basado en el analizador Rhino de Mozilla. Close Compiler tiene un modo simple para realizar comprobaciones de código básicas, pero también tiene modos más avanzados para realizar comprobaciones adicionales y aplicar declaraciones de tipos especiales.

Close Compiler informa errores en el código JavaScript, pero también crea versiones minimizadas de JavaScript. El compilador elimina espacios en blanco, comentarios y variables no utilizadas y simplifica las declaraciones largas para hacer un script lo más pequeño posible.

Google pone a disposición una versión simple de su compilador en la Web , pero la mayoría de las veces querrás descargar Closure Compiler y ejecutarlo localmente.

 

El compilador de cierre generará una lista de archivos en un único archivo minimizado después de verificar su código. Puede ejecutarlo así después de haber descargado el compiler.jararchivo.

java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js

Elegir el corrector adecuado

En mis proyectos combino Cierre Compiler con JSHint. Close Compiler realiza la minimización y la verificación básica, mientras que JSHint maneja el análisis de código más complejo. Los dos funcionan bien juntos y cada uno cubre algunas áreas que el otro no cubre. Además, puedo utilizar las capacidades de extensión de JSHint para escribir fichas personalizadas. Un verificador común que escribo verifica funciones particulares que no quiero, como llamar a funciones que no quiero permitir en mi proyecto.

Ahora que hemos visto algunas fichas, veamos un código incorrecto. Todos estos seis ejemplos son códigos que nunca deberías escribir y son puntos donde los verificadores de códigos te evitarían problemas.

Este artículo utiliza JSHint para la mayoría de los ejemplos, pero el compilador de cierre produciría advertencias similares.

== Contra ===

JavaScript es un lenguaje escrito dinámicamente . No es necesario declarar tipos cuando codifica, pero existen en tiempo de ejecución. JavaScript ofrece dos operadores de comparación para manejar estos tipos dinámicos: ==y ===. Veamos un ejemplo.

var n = 123;var s = '123';if (n == s) { alert('The variables were equal');}if (n === s) { alert('The variables were identical');}

El ==operador compara los valores de los dos objetos. Convierte los objetos y los compara por separado de sus tipos. El ===operador compara los tipos de objetos y los valores. En este caso, el primer ifbloque mostrará una alerta y el segundo ifbloque no, porque ny stienen el mismo valor pero no el mismo tipo.

El ==comparador es una reliquia de las raíces del lenguaje C de JavaScript. Usarlo casi siempre es un error: comparar valores separados de los tipos rara vez es lo que el desarrollador pretende hacer. En realidad, el número "ciento veintitrés" es diferente de la cadena "uno dos tres". Estos operadores son fáciles de escribir mal y aún más fáciles de leer mal.

Verifique este código con JSHint y obtendrá esto:

test.js: line 9, col 12, Expected '===' and instead saw '=='.

Variables indefinidas y definiciones tardías

Comencemos con un código simple:

function test() { var myVar = 'Hello, World'; console.log(myvar);}

¿Ves el error? Cometo este error todo el tiempo. Ejecute este código y obtendrá un error:

ReferenceError: myvar is not defined

Hagamos el problema un poco más difícil de detectar:

function test() { myVar = 'Hello, World'; console.log(myVar);}

Ejecute esto y obtendrá:

Hello, World

Este segundo ejemplo funciona, pero tiene algunos efectos secundarios muy inesperados. Las reglas para declarar variables de JavaScript y los alcances en los que terminan son, en el mejor de los casos, confusas. Noticias del cadiz

 

En el primer caso, JSHint te dirá esto:

test.js: line 3, col 17, 'myvar' is not defined.

En el segundo caso te dirá esto:

test.js: line 2, col 5, 'myVar' is not defined.test.js: line 3, col 17, 'myVar' is not defined.

El primer caso le salva de un error de ejecución. No es necesario que pruebe su aplicación: JSHint encontrará el error por usted. El segundo caso es peor porque las pruebas no encontrarán el error.

El problema del segundo caso es insidiosamente sutil y complejo. La variable myVarahora escapó del alcance de su función y se elevó al alcance global para toda la página. Esto significa que existirá y tendrá un valor de Hello, Worlddespués de que se haya ejecutado la testfunción. Esto se llama “contaminación de alcance global”.

La myVarvariable existirá para todas las demás funciones que se ejecuten después de la testfunción. Ejecute el siguiente código después de haber ejecutado la testfunción:

console.log('myVar: ' + myVar);

Aún lo obtendrás Hello, World. La myVarvariable permanecerá alrededor de su código como si fuera moho, causando errores complicados que no encontrará hasta las 3:00 a.m. de la noche anterior a su lanzamiento, todo porque olvidó escribir var.

Reutilización de variables

La redefinición de variables está permitida en JavaScript, pero casi siempre es un accidente. Echar un vistazo:

function incrementCount(counter) { if (counter.count) { counter.count++; } else { var counter = 1; counter.count = counter; }}

En esta función estamos incrementando la countpropiedad en el objeto que se pasó, pero necesitamos agregar la propiedad si aún no existe. ¿Ves el error?

Esta función nunca agregará ni incrementará un contador en nada. La elsedeclaración siempre será llamada y redefinirá el argumento de la función counter. Básicamente, esta función crea un nuevo objeto, le asigna una propiedad y luego pierde el objeto cuando la función regresa. Nunca cambiará el objeto que se pasó.

Este simple error tipográfico hará que el código se ejecute sin errores pero producirá un resultado muy extraño.

JSHint te dirá esto:

test.js: line 21, col 21, 'counter' is already defined.

Llaves en bloques, bucles y condicionales

if (false) doSomethingElse(); doSomething();

¿Este código doSomethingo doSomethingElse? A primera vista, siempre pienso que no será así doSomethingo doSomethingElse... Así es como funciona en Python, pero no en JavaScript. JavaScript tratará la línea después de la ifdeclaración simplemente como parte del bloque; la sangría no importa.

Este problema tiene que ver simplemente con la legibilidad del código. Si no puedes entender lo que hará el código, entonces escribirás errores.

A Python y CoffeeScript les gusta saltarse las llaves. Eso podría funcionar bien en lenguajes que garantizan formatear bien los espacios en blanco, pero JavaScript es más flexible que eso. JavaScript permite mucha sintaxis extraña y las llaves te evitarán problemas.

 

if (false) { doSomethingElse(); doSomething();}

Agregue las llaves y siempre hará que el código sea más legible. Sáltelos y JSHint le dirá esto:

test.js: line 27, col 5, Expected '{' and instead saw 'doSomething'.

Comillas simples y dobles

console.log("This is a string. It's OK.");console.log('This string is OK too.');console.log("This string " + 'is legal, but' + "really not OK.");

JavaScript le permite definir una cadena con comillas simples o dobles. Es bueno tener flexibilidad, como cuando se define HTML, pero la flexibilidad adicional puede generar un código muy inconsistente.

Google tiene una guía de estilo de código que siempre utiliza comillas simples para las cadenas, de modo que no tengan que escapar de las comillas dobles en HTML. No puedo argumentar que las comillas simples sean mejores que las dobles, pero puedo defender la coherencia. Mantener todo coherente hace que el código sea más legible.

JSHint le advertirá sobre comillas mixtas como esta:

test.js: line 31, col 27, Mixed double and single quotes.

Copiar y pegar o escribir mal una cotización es fácil. Una vez que tenga una cita incorrecta, le seguirán otras, especialmente si muchas personas están editando el archivo. Los analizadores estáticos ayudarán a mantener las cotizaciones consistentes y evitarán una gran limpieza en el futuro.

Complejidad ciclomática

La complejidad ciclomática es la medida de cuán complejo es un bloque de código determinado. Mire el código y cuente la cantidad de caminos que posiblemente podrían ejecutarse: ese número es su complejidad ciclomática.

Por ejemplo, este código tiene una complejidad ciclomática de 1:

function main() { return 'Hello, World!';}

Solo puedes seguir un camino a través de este código.

Agreguemos un poco de lógica condicional:

function main() { if (true) { return 'Hello, World!'; } else { return 'Hello, unWorld!'; }}

La complejidad ciclomática ha saltado a 2.

El código ideal es fácil de leer y comprender. Cuanto mayor sea la complejidad ciclomática, más difícil será entender el código. Todo el mundo está de acuerdo en que una alta complejidad ciclomática es mala, pero nadie se pone de acuerdo en cuanto a un límite; 5 está bien y 100 es demasiado alto, pero hay muchas áreas grises en el medio.

Si la complejidad ciclomática llega al límite predefinido, JSHint se lo informará.

test.js: line 35, col 24, This function's cyclomatic complexity is too high. (17)

JSHint es el único de los tres inspectores que analiza la complejidad ciclomática. También te permite establecer el límite. Vaya por encima del maxcomplexitynúmero que ha configurado y JSHint le avisará. Me gusta establecer el límite en 14, pero lo subiré un poco más en proyectos en los que analizo mucho o cuando tengo otras razones para necesitar muchas rutas de código.

La verdadera razón por la que el número de complejidad es importante es que le indica cuándo refactorizar su código. La primera vez que escribes una función larga, siempre tiene sentido. Pero si espera seis meses y luego regresa para corregir errores, se alegrará de haberse tomado el tiempo para hacerlo más fácil de leer.

 

La complejidad ciclomática suele desaparecer con las listas de lavandería. Por ejemplo, creé un calendario y quería obtener el primer día de la semana correcto para cada país. Tenía una función que se parecía a esto:

function getFirstDay(country) { if (country === 'USA') { return 'Sunday'; } else if (country === 'France') { return 'Monday'; } else if…}

Admití muchos países, por lo que la complejidad ciclomática creció rápidamente a más de 50. Aunque el código era muy fácil de leer, la cantidad de rutas era alta, por lo que mi analizador de código se quejó. Al final, dividí la función para que la complejidad estuviera por debajo de mi máximo. Fue un truco para este caso particular, pero es un pequeño precio a pagar por un código más limpio en general.

Verifica todo lo que editarás más de una vez

Los verificadores estáticos encuentran errores que no encontraría con pruebas simples. También encuentran errores en el tiempo de compilación, a diferencia del tiempo de ejecución: esos errores a media noche que sólo aparecen cuando una docena de personas intentan hacer lo mismo. Encontrar todos esos errores sutiles es un proceso largo y doloroso sin verificación de código.

Comencé este artículo afirmando que siempre uso un analizador de código, pero no lo hago en un caso: con código desechable. Me gusta usar prototipos rápidos para mostrar ideas interactivas y ayudar a mi equipo a reunirse sobre cómo debería funcionar algo. Esos prototipos son código de una sola escritura; Nunca necesito corregir errores en ellos porque tiraré los prototipos unas semanas después. Este código desechable existe únicamente para demostraciones rápidas y no me importa si tiene errores sutiles. Sin embargo, todo lo que me importa se analiza.

Corregir este tipo de errores al inicio de un proyecto es fácil; encontrarlos la noche anterior a tu liberación te volverá loco. Los analizadores de código me han salvado el trasero muchas veces y también salvarán el tuyo.

Imagen de portada creada por Ruiwen Chua .

Otras lecturas

  • Stylelint: la hoja de estilo Linter que siempre quisimos
  • ESLint: el Linter JavaScript de próxima generación
  • Por qué es importante el estilo de codificación
  • Por qué debería considerar los gráficos para su próximo proyecto GraphQL

(al, ml, da, mrn)Explora más en

  • Codificación
  • javascript
  • Errores
  • Desarrollo web





Tal vez te puede interesar:

  1. ¿Deberían abrirse los enlaces en ventanas nuevas?
  2. 24 excelentes tutoriales de AJAX
  3. 70 técnicas nuevas y útiles de AJAX y JavaScript
  4. Más de 45 excelentes recursos y repositorios de fragmentos de código

Terribles errores de JavaScript que se deben evitar con un analizador de código estático

Terribles errores de JavaScript que se deben evitar con un analizador de código estático

Índice JSLint, JSHint y compilador de cierre

programar

es

https://aprendeprogramando.es/static/images/programar-terribles-errores-de-javascript-que-se-deben-evitar-con-un-analizador-de-codigo-estatico-874-0.jpg

2024-05-20

 

Terribles errores de JavaScript que se deben evitar con un analizador de código estático
Terribles errores de JavaScript que se deben evitar con un analizador de código estático

Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

 

 

Top 20