Los meta comentarios son una forma de imbuir puntos de ruptura dentro del código fuente. Esto es bastante útil, si estas escribiendo el código, y quieres añadir un punto de ruptura en alguna parte. Además, proporciona flexibilidad en la manera en que escribes el código fuente. Y eso es Bueno. Existen tres meta comentarios distintos.
//@JSD_LOG
insertará un punto de ruptura
que ejecutará el script que le sigue
sin detenerse. El resultado de la evaluación
se registrará en la Sesión Interactiva.//@JSD_BREAK
insertará
un punto de ruptura que ejecutará el script que le sigue y se detendrá en el caso
de que el resultado sea true.//@JSD_EVAL
insertará un
punto de ruptura que ejecutará el script que le sigue sin parar
y sin registrar el resultado.Se usan de la siguiente forma:
function x() { ... [código script] //@JSD_EVAL [código script] ... [código script] }
Es importante darse cuenta, que, como los puntos de ruptura, los meta comentarios
no se ejecutan cuando Venkman no está siendo ejecutado. Pero a diferencia de
la palabra clave debugger
, esto es un comentario JavaScript real,
con lo que no tendrás ningún problema con ningún navegador.
En Mozilla, carga el siguiente archivo, venkman_example_9.html. Es horrible, pero muestra los tres diferentes tipos de meta comentarios en un solo archivo. Si ejecutaras el script de forma normal, simplemente imprimiría el factorial de los números del 0 al 9. Nada demasiado impresionante.
Si examinas el código, verás que la función factorial
no comprueba si el valor es un número negativo. Si le pasamos un número negativo a fac
,
devolverá "1", lo cual es incorrecto para los números negativos
(no existe el factorial, de un número negativo.)
Inicia Venkman, y echa un vistazo al código fuente.
Figura 55.
Viendo el código fuente de venkman_example_9.html
Antes de que los metacomentarios hagan algo, necesitas rastrearlos. En el panel de Scripts Cargados, haz click con el botón derecho sobre venkman_example_9.html.
Figura 56.
Click con el botón derecho, para rastrear el archivo en busca de meta comentarios.
Enseguida te darás cuenta, de que ahora el código fuente tiene puntos de ruptura.
Figura 57.
Usando meta comentarios para establecer puntos de ruptura en tu código automáticamente (pulsa para una versión sin escalar).
Como podemos ver, los puntos de ruptura se indican tanto en el panel Scripts Cargados (con el punto rojo), como en el panel de Puntos de ruptura, y con las "B"s en el panel del código fuente.
Lo que en realidad hacen los meta comentarios, es hacer que Venkman cree los puntos de ruptura fuertes por ti en la línea posterior a los meta comentarios (recuerda, que usar un punto de ruptura hace que Venkman pare justo antes de ejecutar la línea en la que está ¿ok?) Puedes hacer click con el botón derecho, y seleccionar las propiedades de cualquiera de estos puntos de ruptura. Aquí, en la figura 58, he seleccionado las propiedades del punto de ruptura de la línea 6.
Figura 58.
Una hoja de propiedades de punto de ruptura generada automaticamente.
Ahora que hemos cargado todos los meta comentarios, intenta ejecutar el script
(volviendo a cargar Mozilla). Basicamente, la idea es, que una vez que
los meta comentarios han sido rastreados, i
tomará un valor negativo en la 7ª
iteración (para el cual fac
no nos dará un resultado
correcto).
Pero dado que ahora tenemos un punto de ruptura
condicional, en fac
, programado para parar la ejecución solo si
el número pasado es negativo, puedes cambiar facN
, una vez
se le pasa a fac
un número negativo.
Figura 59.
Venkman ha parado su ejecución, porque n<0
era cierto. Aquí, he
preguntado que es n
, y voy a establecer facN
a "passed number was negative!" ('el número pasado era negativo!) (pulsa para una versión no escalada).
Tal como puede verse en la captura de pantalla, he parado la ejecución, y voy a devolver el mensaje "wrong number passed" (se ha pasado un número incorrecto). Normalmente, se habría devuelto 1, que es incorrecto como factorial de -4 (no hay factorial de -4 por supuesto). Esto, muestra lo siguiente en Mozilla:
factorial 0 = 1 factorial 1 = 1 factorial 2 = 2 factorial 3 = 6 factorial 4 = 24 factorial 5 = 120 factorial 6 = 720 factorial -4 = passed number was negative! factorial 8 = 40320 factorial 9 = 362880
Por supuesto, -4 solo se pasó a fac
, por el código de nuestro punto de ruptura,
pero sirve para coger el concepto. Además, en lugar de simplemente devolver una cadena,
podríamos haber lanzado una excepción, comprobando como reaccionaba nuestro código.
El uso de "Pretty Print" (literalmente Impresión Bonita), nos permite ver una función, en la forma en que JavaScript
la ve. Esto es útil, cuando la función original ni tan siquiera existe en tu código,
por ejemplo si se construyó usando eval
, o
métodos similares (setTimeout
, etc). Además, también es util
cuando el código fuente se ha intentado ofuscar deliberadamente (la llamada
"protección de código fuente"). En Mozilla, carga el archivo
venkman_example_10.html, que muestra algunos
ejemplos de como utilizar "Pretty Print".
Cuando cargamos Venkman, las diferentes funciones tendrán este aspecto:
function foo() { var s = "function bar1(x) {debugger;return x+1;}"; eval(s); return bar1(1); } function bar2(n) { while(n) n--; return "blah"; } function fac(n){if(n<=0){return 1;}else{return n*fac(n-1);}}
Ten en cuenta, que la primera función (foo
), contiene
otra función imbuida, llamada bar1
. Esto nos servirá como ejemplo
de como Pretty Print nos permite ver funciones que no están "ahí".
En este ejemplo, bar1
es una cadena muy simple,
pero en un ejemplo real, podría ser cualquier cantidad
de código, generado de la manera que quisieras.
El segundo ejemplo es mas simple, muestra un bucle while
,
pero no introduje las llaves opcionales. Finalmente,
he escrito una función factorial recursiva. Como puedes ver, está escrita
en una forma compacta, gracias al script JavaScript Crunchinator de BrainJar, el cual basicamente
compacta el código (¡e indirectamente también lo hace mas dificil de leer!).
Vamos a utilizar la función Pretty Print para ver las funciones bar1
,
bar2
y fac
. Si quieres, examina
el código fuente en Venkman. Especialmente observa como la cadena
s
(de la que se generará la función bar1
)
contiene la palabra clave debugger
. Cuando estes listo, vuelve a cargar la página, Venkman
debería parar instantaneamente en la palabra clave debugger
.
Figura 60.
Venkman ha parado la ejecución en una función que no podemos ver directamente, de forma que
podría parecer "erroneo", pero no hay ningún error. Puedes utilizar la función
"Pretty Print", para ver donde se ha parado realmente Venkman
(pulsa para ver una versión no escalada).
Puede parecer un poco raro, que Venkman halla parado en la línea del
eval
(dado que esa no es la línea en la que está la palabra clave debugger
.)
Pero lo que está pasando es, que eval
ha evaluado y declarado la función bar1
,
y entonces, cuando en la línea 7, se invoca a bar1
, vuelve al lugar donde
se definió la función (línea 6, el eval
),
y ahí, se para la ejecución debido a la palabra clave debugger
. Para poder ver la
función bar1
apropiadamente, pulsa sobre "Pretty Print".
Figura 61.
Utilizando Pretty Print para revelar el código real de bar1
, decompilado
según como lo ve el engine JavaScript (pulsa para ver una versión no escalada).
También puedes añadir puntos de ruptura en este código, y si lo haces,
los puntos de ruptura también se verán reflejados en el panel del código fuente "normal".
Por ahora, prueba a ejecutar el código de la función paso a paso (usando "Step out"),
y coloca un punto de ruptura en la línea 11,
continía después ejecutando el código paso a paso hasta la función bar2
. Debería aparecer una
nueva pestaña, para mostrar la versión Pretty Print de bar2
.
Además, mientras el depurador no está activo, puedes también ver la versión Pretty Print de las funciones. Por supuesto, cuando el script no está siendo ejecutado, Venkman no puede mostrar la versión Pretty Print de funciones que no existen aún (tal como el ejemplo con eval).
Figura 62.
Código fuente de bar2
, decompilado de la representación JavaScript interna.
Figura 63.
Código fuente de fac
, decompilado de la representación JavaScript interna.
Este último ejemplo en concreto es mucho mas legible que la versión original
function fac(n){if(n<=0){return 1;}else{return n*fac(n-1);}}
Usar Pretty Print es una muy buena forma de ver código mal escrito. Desafortunadamente
también elimina los comentarios. Puedes continuar ejecutando el código línea por línea, añadir puntos de ruptura, y cualquier
otra cosa que pudieras hacer con código normal.
Pero cuando se usa para escrutar código escrito
y declarado dentro de eval
, podría ser todo lo que tienes
(en tiempo de ejecución). También recuerda, que todo lo comentado para eval
se aplica igualmente
a setTimeout
.
Aunque tecnicamente esto debería estar en la sección depuración basica,
creo que tiene mas sentido situarlo aquí
(o al menos aquí se puede entender mejor, o eso espero.) Venkman te permite saltar
código eval
, si no quieres molestarte con él.
En Mozilla, carga el siguiente archivo, venkman_example_exclude_eval.html. Verás que hay dos lugares,
donde hay llamadas a eval
, que contienen la palabra clave debugger
.
Así que queremos saltarnos estas dos.
Hacer esto es tan simple como encontrar el archivo, del cual quieres excluir
el código eval
(también es válido para setTimeout
etc.) Simplemente haz click con el botón derecho sobre el archivo como se muestra en la figura 64.
Figura 64.
Excluyendo el código de tipo eval
de la depuración (pulsa para obtener una versión no escalada).
Si vuelves a cargar Mozilla (con Venkman ejecutándose), verás que no se muestra
la ventana de Venkman, como pasaría normalmente, con scripts que contienen
la palabra clave debugger
.
Profiling significa medir la rapidez con la que se ejecuta tu programa. Y el botón
"Profile" de Venkman hace justamente eso. Tradicionalmente, la forma de medir
el rendimiento de un script, consistía en incluir dentro del código un montón de objetos Date
,
y aplicar algo de matemáticas sobre ellos.
function foo() { var startDate = new Date(); var startTime = startDate.getTime(); // código var endDate = new Date(); var endTime = endDate.getTime(); // tiempo total de ejecución del script (en milisegundos): var totalTime = endTime - startTime; }
Esto nos puede servir para trozos pequeños de código, o para comprobar si "esto funciona". Pero para medir el rendimiento de código complejo, es poco útil.
Para demostrar el uso de Profile, he creado una tabla DHTML, utilizando mi script de fecha. Basicamente, lo que ocurre es que he creado una fecha aleatoria, y he usado todas las opciones que permite mi script, construyendo una fila de la tabla con la salida de mi script, haciendo esto 100 veces. Y finalmente, vamos a ordenar la tabla, de forma que vaya del mas viejo, al mas nuevo (para los profesionales de JavaScript: el ejemplo está mal escrito de forma deliberada). Ejecuta el script cargando la página venkman_example_11.html (cuidado, ¡puede llevar un rato el que se ejecute!)
Ejecuta de nuevo Venkman, y simplemente pulsa sobre el botón "Profile", para comenzar el profiling.
Figura 65.
Se ha activado el profiling, y Venkman está tomando nota de todo
lo que está ocurriendo.
Ahora mismo, Venkman está tomando nota de todo lo que está ocurriendo. Puedes volver a Mozilla, y recargar la página. Una vez que halla acabado, vuelve a Venkman, y para el profiling. Entonces en el menú "File" (Archivo), selecciona "Save Profile Data as ..." (Guardar Información de Profile como ...), e introduce el nombre del archivo donde quieras guardar la información. También es importante que introduzcas un tipo de archivo, ya que Venkman puede guardar la información en unos cuantos formatos diferentes. HTML es el mas accesible. Puedes acceder al informe del profile que cree (puede que las barras se vean un poco mal.)
En el informe generado, puedes ver todo tipo de información sobre todas las
funciones, como cuantas veces se ha llamado, cuanto duraron las llamadas como media,
la llamada mas larga, la mas corta, el tiempo total de las llamadas, y otras cosas. Observa,
que si una función, por ejemplo foo
, llama a otra función
bar
, el tiempo de foo
incluye tanto el tiempo que tardó en ejecutarse la propia función foo
,
como por el tiempo que tardó bar
.
Otra cosa importante que señalar, es que puedes excluir archivos, y funciones individuales para que no aparezcan en el informe. Simplemente pulsa en el archivo o la función que no quieras que se incluya, y haz click con el botón derecho sobre él.
Figura 66.
Cómo evitar que se incluya una función en el profiling.
Figura 67.
Cómo evitar que se incluya un archivo (y las funciones que incluye) en el profiling.
El profiling nos permite identificar los puntos donde se están produciendo cuellos de botella. Pero por supuesto, ninguna tabla de estadísticas te va a dar por si sola un código eficiente. Tendrás que saber como reparar estos problemas.
Una vez que hallas terminado con el profiling, no te olvides de borrar la información acumulada hasta ese momento. Si no lo haces, el próximo informe incluirá información pasada (y probablemente esto no sea lo que quieres.)
Figura 68.
Es importante borrar la información de profiling.
También puedes borrar la información de funciones o archivos individuales, siguiendo el mismo procedimiento mostrado, pero seleccionando "Clear Profile Data" (Borrar Información de Profile) en su lugar.
Una última cosa interesante sobre el profiling, es si ya has hecho el profile, y decides que no quieres la información de todo, puedes obtener la información de profile de las funciones y/o archivos que quieras.
Figura 69.
Guardando la información profiled de funciones individuales,
o de un archivos completo (y de las funciones que contiene)
(pulsa para obtener una versión no escalada).
Uff, un poco aburrido ¿verdad? Bueno, según los logs de mi servidor ¡poca gente llega tan lejos! Dado que tú lo has hecho, me encantaría escuchar cualquier comentario que puedas tener, si has encontrado algún error, o cualquier otra cosa, que pienses que podría mejorarse.
Independientemente de lo mal escrita que esté la guía, ahora deberías
ser capaz de utilizar Venkman para encontrar errores de JavaScript realmente incomprensibles.
Yo aún utilizo bastante amenudo (casi siempre) alert
s para depurar.
Son rápidos, y la mayor parte de los errores en el código no son muy complejos.
Pero algunas veces aparece un error verdaderamente complicado, o
estás trabajando con bastante código (afortunadamente
yo no lo suelo hacer muy amenudo), y es entonces cuando lo que has aprendido te puede resultar útil, y te permitirá
depurar tu código como un profesional.
Me gustaría dar las gracias a unas pocas personas, primero, a Robert Ginda, por contestar mis preguntas sobre los aspectos mas oscuros de algunas características de Venkman, además de a Doron Rosenberg por haber hecho que me enlacen un montón de sitios, ¡y también a la gente que me mandó sugerencias, en la primera revisión de esta guía!