Juan Carlos Pérez González 2. Manexo da sintaxe da linguaxe. • Variables e constantes: ámbito de uso. • Tipos de datos: conversión entre tipos. • Asignacións. Operadores. • Expresións. • Comentarios ao código. • Sentenzas e bloques de sentenzas. Decisións. Bucles. • Uso de contornos de desenvolvemento integrados. • Depuración e documentación do código. 1 Juan Carlos Pérez González 1. Variables e constantes: ámbito de uso. Una variable es una ubicación temporal de memoria donde el programador guarda un cierto valor que usará posteriormente en la ejecución del script. La declaración de una variable en JS presenta dos características: • puede ser opcional: • es de tipado débil Ello permite dos mecanismos de declaración: • Explícita: viene determinada por el uso del comando var. D • Implícita: la declaración del tipo viene dada por la propia asignación de valor a la variable sin necesidad de usar el comando var. identificador=valor-inicial; <script> var precio=0; //declaracion explícita variable global function mensaje(){ var producto=; //declaración explícita variable local cantidad=3 //declaración implícita. Será tratada como variable global …. } </script> Una variable debe cumplir las siguientes reglas: • solamente puede estar formado por letras, números y los símbolos ( $ y _ ) • el primer carácter no puede ser un número solo una letra, $ o _. Ejemplos: identificador=valor-inicial; <script> var $precio=0; //declaracion explícita variable global function mensaje(){ var _producto=; //declaración explícita variable local 23cantidad=3 //Incorrecto cantidad@=3 //Incorrecto ….} </script> Por otro lado existen una serie de palabras reservadas que el compilador no 2 Juan Carlos Pérez González admitirá a la hora de ejecutar un script. Un tipo especial de variable es la constante que como se sabe nunca cambia de valor una vez establecido. const tasa=20; //Declaración constante JS Hay tres ámbitos básicos para una variable: • Global: se puede utilizar en cualquier lugar del código. Generalmente se declara fuera de cualquier función o bien la declaramos en cualquier lugar pero sin utilizar el comando var. • Local: solo son utilizadas dentro de la función donde fueron declaradas. • Bloque: la variable se declara dentro de un bloque, foreach, while o for y su uso se restringe a ese bloque y no puede ser accedido desde el exterior. De momento este último no se aplica en JS. 2. Tipos de datos: conversión entre tipos. Una de las características de JS es su tipado débil es que no define el tipo de variable a la hora de definirla. Además permite que una variable almacene diferentes tipos de datos siendo este un tipado dinámico. Este hecho parece algo confuso y hasta caótico sobre todo cuando se proviene de lenguajes de programación fuertemente tipados sobre todo porque obliga al programador en todo momento tener un control sobre el código ante el riesgo de errores en las operaciones. 3 Juan Carlos Pérez González Veamos los tipos de datos en JS: • Numérico: almacena valores enteros y decimales estos últimos con el punto como separador “.” var precio=53; var precio=53.12; • Cadena (string): estos valores se acotan entre comillas dobles o simples. var mensaje=’esto es un mensaje’; var mes=”enero”; var cadena = “no puede mezclarse’ //error Caracteres Especiales • Booleano: presenta dos valores true o false. Se utiliza en las evaluaciones condicionales • Null: se utiliza para inicializar las variables que representarán objetos. Cuando se inicializa a null indica que el objeto aún no ha sido creado. • Objeto: son abstracciones que permiten modelar la realidad mediante métodos y propiedades. JS no trabaja con el concepto clase a pesar de estar OO. Para crear un objeto se realiza de la siguiente forma: var miObjeto=new Object(); Si aún no ha sido creado entonces es utiliza null • Undefined: JS lo utiliza para identificar las variables que aún no han sido inicializadas. Identificación de tipos. 4 Juan Carlos Pérez González JS proporciona una función que permite identificar el tipo de dato que representa una variable. Se llama typedef. • Toda variable definida que no se le asignó ningún valor contiene el tipo undefined. • Las variables inicializadas con valor null se interpretan como objetos y devuelve Object. • Las variables cuyo contenido sean cadenas de texto devuelven el tipo String. Ejemplo: Codifica y ejecuta el siguiente código. <html> <head> <script> var a; var b=null; var c=”AA” vard d=12; var e=true; function verTipos(){ alert(typeof(a)); alert(typeof(b)); alert(typeof(c)); alert(typeof(d)); alert(typeof(e)); } </script> </head> <body> <h2>Tipos de datos</h2> <ul> <li>Indefinido</li> <li>Objeto</li> <li>Cadena</li> <li>Numérico</li> 5 Juan Carlos Pérez González <li>Booleano</li> </ul> <hr/> <input type=”button” onclick=”verTipos();” value=”Ver”></input> </body> </html> El tipado dinámico a veces genera errores, por ejemplo, el símbolo +. Generalmente se usa como operador matemático pero en presencia de cadenas de texto las concatena dando lugar a errores si el programador no está atento. 3. Asignacións. Operadores. La operación de asignación utiliza el signo =. var e=25; var d=null; var d=e; //d tomará el valor de 25 • Operadores Aritméticos: JS permite realizar manipulaciones matemáticas sobre el valor de las variables numéricas. Los operadores definidos son: suma (+), resta (-), multiplicación (*) y división (/). Ejemplo: var numero1 = 10; var numero2 = 5; resultado = numero1 / numero2; // resultado = 2 resultado = 3 + numero1; // resultado = 13 resultado = numero2 – 4; // resultado = 1 resultado = numero1 * numero 2; // resultado = 50 Además de los cuatro operadores básicos, JS define otro operador matemático. s trata del operador "módulo", que calcula el resto de la división entera de dos números. Si se divide por ejemplo 10 y 5, la división es exacta y da un resultado de 2. El resto de esa división es 0, por lo que módulo de 10 y 5 es igual a 0. Sin embargo, si se divide 9 y 5, la división no es exacta, el resultado es 1 y el resto 6 Juan Carlos Pérez González 4, por lo que módulo de 9 y 5 es igual a 4. El operador módulo en JS se indica mediante el símbolo %, que no debe confundirse con el cálculo del porcentaje: var numero1 = 10; var numero2 = 5; resultado = numero1 % numero2; // resultado = 0 numero1 = 9; numero2 = 5; resultado = numero1 % numero2; // resultado = 4 Los operadores matemáticos también se pueden combinar con el operador de asignación para abreviar su notación: var numero1 = 5; numero1 += 3; // numero1 = numero1 + 3 = 8 numero1 -= 1; // numero1 = numero1 - 1 = 4 numero1 *= 2; // numero1 = numero1 * 2 = 10 numero1 /= 5; // numero1 = numero1 / 5 = 1 numero1 %= 4; // numero1 = numero1 % 4 = 1 • Incremento y decremento Estos dos operadores solamente son válidos para las variables numéricas y se utilizan para incrementar o decrementar en una unidad el valor de una variable. var numero = 5; ++numero; alert(numero); // numero = 6 De forma equivalente, el operador decremento (indicado como un prefijo -- en el nombre de la variable) se utiliza para decrementar el valor de la variable: var numero = 5; --numero; 7 Juan Carlos Pérez González alert(numero); // numero = 4 Los operadores de incremento y decremento no solamente se pueden indicar como prefijo del nombre de la variable, sino que también es posible utilizarlos como sufijo. En este caso, su comportamiento es similar pero muy diferente. En el siguiente ejemplo: var numero = 5; ++numero; alert(numero); // numero = 6 El resultado de ejecutar el script anterior es el mismo que cuando se utiliza el operador ++numero, por lo que puede parecer que es equivalente indicar el operador ++ delante o detrás del identificador de la variable. Sin embargo, el siguiente ejemplo muestra sus diferencias: var numero1 = 5; var numero2 = 2; numero3 = numero1++ + numero2; // numero3 = 7, numero1 = 6 var numero1 = 5; var numero2 = 2; numero3 = ++numero1 + numero2; // numero3 = 8, numero1 = 6 Si el operador ++ se indica como prefijo del identificador de la variable, su valor se incrementa antes de realizar cualquier otra operación. Si el operador ++ se indica como sufijo del identificador de la variable, su valor se incrementa después de ejecutar la sentencia en la que aparece. • Lógicos Los operadores lógicos son imprescindibles para realizar aplicaciones complejas, ya que se utilizan para tomar decisiones sobre las instrucciones que debería 8 Juan Carlos Pérez González ejecutar el programa en función de ciertas condiciones. El resultado de cualquier operación que utilice operadores lógicos siempre es un valor lógico o booleano. • Negación Uno de los operadores lógicos más utilizados es el de la negación. Se utiliza para obtener el valor contrario al valor de la variable: var visible = true; alert(!visible); // Muestra "false" y no "true" La negación lógica se obtiene prefijando el símbolo ! al identificador de la variable. El funcionamiento de este operador se resume en la siguiente tabla: variable !variable true false false true Sin embargo, ¿qué sucede cuando la variable es un número o una cadena de texto? Para obtener la negación en este tipo de variables, se realiza en primer lugar su conversión a un valor booleano: • Si la variable contiene un número, se transforma en false si vale 0 y en true para cualquier otro número (positivo o negativo, decimal o entero). • Si la variable contiene una cadena de texto, se transforma en false si la cadena es vacía ("") y en true en cualquier otro caso. var cantidad = 0; vacio = !cantidad; // vacio = true cantidad = 2; vacio = !cantidad; // vacio = false var mensaje = ""; mensajeVacio = !mensaje; // mensajeVacio = true mensaje = "Bienvenido"; mensajeVacio = !mensaje; // mensajeVacio = false 9 Juan Carlos Pérez González • AND La operación lógica AND obtiene su resultado combinando dos valores booleanos. El operador se indica mediante el símbolo && y su resultado solamente es true si los dos operandos son true: variable1 true true false false variable2 variable1 && variable2 true true false false true false false false var valor1 = true; var valor2 = false; resultado = valor1 && valor2; // resultado = false valor1 = true; valor2 = true; resultado = valor1 && valor2; // resultado = true • OR La operación lógica OR también combina dos valores booleanos. El operador se indica mediante el símbolo || y su resultado es true si alguno de los dos operandos es true: variable1 true true false false variable2 variable1 || variable2 true true false true true true false false var valor1 = true; var valor2 = false; resultado = valor1 || valor2; // resultado = true valor1 = false; valor2 = false; resultado = valor1 || valor2; // resultado = false 10 Juan Carlos Pérez González • Relacionales Los operadores relacionales definidos por JS son idénticos a los que definen las matemáticas: mayor que (>), menor que (<), mayor o igual (>=), menor o igual (<=), igual que (==) y distinto de (!=). El resultado de todos estos operadores siempre es un valor booleano: var numero1 = 3; var numero2 = 5; resultado = numero1 > numero2; // resultado = false resultado = numero1 < numero2; // resultado = true numero1 = 5; numero2 = 5; resultado = numero1 >= numero2; // resultado = true resultado = numero1 <= numero2; // resultado = true resultado = numero1 == numero2; // resultado = true resultado = numero1 != numero2; // resultado = false Se debe tener especial cuidado con el operador de igualdad (==), ya que es el origen de la mayoría de errores de programación, incluso para los usuarios que ya tienen cierta experiencia desarrollando scripts. El operador == se utiliza para comparar el valor de dos variables, por lo que es muy diferente del operador =, que se utiliza para asignar un valor a una variable: // El operador "=" asigna valores var numero1 = 5; resultado = numero1 = 3; // numero1 = 3 y resultado = 3 // El operador "==" compara variables var numero1 = 5; resultado = numero1 == 3; // numero1 = 5 y resultado = false Los operadores relacionales también se pueden utilizar con variables de tipo cadena de texto: 11 Juan Carlos Pérez González var texto1 = "hola"; var texto2 = "hola"; var texto3 = "adios"; resultado = texto1 == texto3; // resultado = false resultado = texto1 != texto2; // resultado = false resultado = texto3 >= texto2; // resultado = false Cuando se utilizan cadenas de texto, los operadores "mayor que" (>) y "menor que" (<) siguen el siguiente razonamiento: se compara letra a letra comenzando desde la izquierda hasta que se encuentre una diferencia entre las dos cadenas de texto. Para determinar si una letra es mayor o menor que otra, las mayúsculas se consideran menores que las minúsculas y las primeras letras del alfabeto son menores que las últimas (a es menor que b, b es menor que c, A es menor que a, etc.) • Operadores Bit-a-bit Los operadores bit a bit trata sus operandos como un conjunto de 32 bits (ceros y unos), mas que como números decimales, hexadecimales o octales. Por ejemplo, el número decimal 9 se representa en binario como 1001. Los operadores bit a bit realiza sus operaciones en dicha representación binaria, pero devuelven un valor númerico estandar. Los operadores lógicos bit a bit funcionan de la siguiente manera: • Los operandos son convertido a enteros de 32 bits y expresados como series de bits (ceros y unos). • Cada bit en el primer operando es emparejando con el correspondiente bit en el segundo operando: Primer bit con primer bit, segundo bit con segundo bit.. • La operación se aplica para cada par de bits y el resultado es construido bit a bit. 12 Juan Carlos Pérez González • Operador instanceof Se aplica a objetos. Su función es evaluar si una determinada variable de tipo objeto es de un tipo concreto. <script> var fecha=new Objec(); alert(fecha instaceof Date) </script> Devuelve falso si fecha no es un valor Date. 4. Expresiones Aprovecharemos este apartado para introducirnos brevemente en el campo de las expresiones regulares en JS. Una expresión regular es un patrón: una expresión que define todas las cadenas o subcadenas que cumplen con ciertos criterios. Por ejemplo, un criterio puede ser “contener una a”. Hemos de tener en cuenta que a efectos de análisis de cadenas de texto no es lo mismo a (minúscula) que A (mayúscula) ó á (con tilde). Es decir, una letra no es lo mismo que esa letra en mayúsculas o esa letra con tilde, diéresis o cualquier otro signo de puntuación. De hecho, quienes estén habituados a trabajar con códigos de caracteres como ASCII ó Unicode ya sabrán que una letra minúscula tiene distinto código numérico que esa misma letra mayúscula. A un computador no podemos indicarle con una frase cuál es el patrón que queremos comprobar, tendremos que indicárselo con una sintaxis normalizada. Es frecuente encontrar código donde se hace alusión a los siguientes términos: • regex: abreviatura de regular expression (expresión regular) • pattern: patrón • match: coincidencia (cadena que contiene el patrón). En la siguiente tabla se reflejan los caracteres principales para construir expresiones regulares. 13 Juan Carlos Pérez González Carácter Significado Ejemplo Backslash o carácter de escape. Sirve para anular un \ carácter especial y hacer que se considere como si Ver más abajo fuera un carácter normal. barco a Donde a es una letra cualquiera. Indica que el patrón incluye una a en el orden especificado. Cadenas que tienen a ‘barco’ como subcadena (incluido barco mismo) {n} El carácter anterior aparece exactamente n veces, siendo n un entero positivo. ca{3}t{3}e Hace match si una subcadena es caaattte. ca{3,}te {n,} El carácter anterior aparece n o más veces, siendo n un entero positivo. Hace match con caaate, caaaate, etc. pero no con cate El carácter anterior aparece un mínimo de n veces y {n,m} un máximo de m veces, siendo n y m enteros positivos. ^ ca{2,5}te El símbolo ^ (denominado “exponente”) indica comienzo de la cadena por ese símbolo. Hace match con caate, caaate, caaaate y caaaaate /^a/ Cadenas que empiezan por a minúscula. ca.e . El símbolo punto indica existencia de cualquier carácter. Cadenas que contienen subcadenas con caxe donde x es cualquier carácter. ^a..e$ $ El símbolo dólar indica que la letra anterior ha de ser obligatoriamente última letra de la cadena Cadenas que empiezan por a y terminan con e, y que contienen exactamente cuatro caracteres (la a inicial, dos intermedios, más la e final) 14 Juan Carlos Pérez González Carácter Significado Ejemplo ^at*e$ * El símbolo asterisco indica que la subcadena contiene el símbolo al que precede cero o más veces. Cadenas que empiezan por a, terminan por e, y entre ambos tienen cero, una o muchas t´s (pero no ningún otro carácter). ^at{0,}e$ {0,} Equivalente al símbolo asterisco Igual que el anterior ^at+e$ + El símbolo más indica que la subcadena contiene el símbolo al que precede una o más veces. Cadenas que empiezan por a, terminan por e, y entre ambos tienen una o muchas t´s (pero no ningún otro carácter). {1,} Equivalente al símbolo + El símbolo interrogación indica opcionalidad: el ? carácter que lo precede puede aparecer 0 ó 1 vez en la subcadena. {0,1} Equivalente al símbolo ?, es decir, el carácter anterior puede aparecer 0 ó 1 vez. El símbolo or genera un match si se encuentra a ó b a|b siendo a ó b dos caracteres cualesquiera que se indiquen. ^at{1,}e$ ^at?e$ Cadenas que empiezan por a, terminan por e, y entre ambos tienen una ninguna t. ^at{0,1}e$ ^a(t|g)e$ Cadenas que empiezan por a, terminan por e, y entre ambos hay una t ó una g. mahatma(?= ghandi) sub1(?=sub2) Hace match sólo si existe una subcadena donde la subcadena sub1 está antes de la subcadena sub2 Hace match con mahatma ghandi pero no con mahatma prasha sub1(?!sub2) Hace match en todas las subcadenas donde la mahatma(?! ghandi) 15 Juan Carlos Pérez González Carácter Significado Ejemplo subcadena sub2 no está después de la subcadena sub1 Hace match con mahatma para, mahatma gon, etc. pero no con mahatma ghandi Hace match con cualquiera de los caracteres [abc] ^[aeiou] indicados dentro de los corchetes (conjunto de caracteres) Cadenas que empiezan por una vocal. Rango de caracteres. Hace match con cualquier carácter comprendido entre el inicial y el final, en [a-z] ^[c-k] orden alfabético. Se pueden definir varios conjuntos uno detrás de otro, por ejemplo: [A-Za-z] indica “letra Cadenas que empiezan por c, d, e, f, g, h, i, j ó k. mayúscula o minúscula”. Complementario o negado de un conjunto de [^abc] ó [^a-z] caracteres. Hace match con cualquier carácter distinto de los definidos en el conjunto de caracteres [^au]$ Hace match con cualquier cadena que no termina en a ni en u ^\d\*\d$ \d Hace match con cualquier número entre 0 y 9 Hace match si la cadena es un número seguido del símbolo * y seguido de otro número. * no es aquí especial por estar precedido del escape \. [0-9] \D \s \S Equivalente a \d Hace match con cualquier carácter que no sea un dígito. Equivale a [^0-9] Hace match con un espacio en blanco (incluye tabuladores y saltos de línea. Hace match con cualquier carácter que no sea ^[0-9]\* [0-9]$ ^ [^0-9] Cadena que no empieza por un número. \s\s Hace match si encuentra dos espacios en blanco [\s\S] 16 Juan Carlos Pérez González Carácter Significado Ejemplo espacio en blanco, tabulador, salto de línea… Hace match con cualquier carácter Hace match con cualquier letra mayúscula, \w minúscula, número o guión bajo. Equivale a [A-Za-z09_]. Tener en cuenta que las letras con tilde quedan Hace match si existe una subcadena con 3 caracteres fuera y habría que añadirlas si queremos. válidos seguidos. Hace match con cualquier carácter que no sea letra \W mayúscula, minúscula, número o guión bajo. Equivale a [^A-Za-z0-9_] Otros \w{3} \W{2,3} Hace match si existe una subcadena con 2 ó 3 caracteres seguidos que no son letras ni números. Existen otros símbolos especiales y combinaciones de símbolos especiales para lograr determinados fines. 5. Comentarios al código. JS define dos tipos de comentarios: los de una sola línea y los que ocupan varias líneas. Ejemplo de comentario de una sola línea: // a continuación se muestra un mensaje alert("mensaje de prueba"); Ejemplo de comentario de varias líneas: /* Los comentarios de varias líneas son muy útilescuando se necesita incluir bastante información en los comentarios */ alert("mensaje de prueba"); 6. Sentencias e bloques de sentencias. Decisiones. Bucles. Los programas que se pueden realizar utilizando solamente variables y operadores son una simple sucesión lineal de instrucciones básicas. 17 Juan Carlos Pérez González Sin embargo, no se pueden realizar programas que muestren un mensaje si el valor de una variable es igual a un valor determinado y no muestren el mensaje en el resto de casos. Tampoco se puede repetir de forma eficiente una misma instrucción, como por ejemplo sumar un determinado valor a todos los elementos de un array. Para realizar este tipo de programas son necesarias las estructuras de control de flujo, que son instrucciones del tipo "si se cumple esta condición, hazlo; si no se cumple, haz esto otro". También existen instrucciones del tipo "repite esto mientras se cumpla esta condición". Si se utilizan estructuras de control de flujo, los programas dejan de ser una sucesión lineal de instrucciones para convertirse en programas inteligentes que pueden tomar decisiones en función del valor de las variables. • if La estructura más utilizada en JS y en la mayoría de lenguajes de programación es la estructura if. Se emplea para tomar decisiones en función de una condición. Su definición formal es: if(condicion) { ... } Si la condición se cumple (es decir, si su valor es true) se ejecutan todas las instrucciones que se encuentran dentro de {...}. Si la condición no se cumple (es decir, si su valor es false) no se ejecuta ninguna instrucción contenida en {...} y el programa continúa ejecutando el resto de instrucciones del script. var mostrarMensaje = true; if(mostrarMensaje) { alert("Hola Mundo"); } En el ejemplo anterior, el mensaje sí que se muestra al usuario ya que la variable mostrarMensaje tiene un valor de true y por tanto, el programa entra dentro del 18 Juan Carlos Pérez González bloque de instrucciones del if. El ejemplo se podría reescribir también como: var mostrarMensaje = true; if(mostrarMensaje == true) { alert("Hola Mundo"); } En este caso, la condición es una comparación entre el valor de la variable mostrarMensaje y el valor true. Como los dos valores coinciden, la igualdad se cumple y por tanto la condición es cierta, su valor es true y se ejecutan las instrucciones contenidas en ese bloque del if. La comparación del ejemplo anterior suele ser el origen de muchos errores de programación, al confundir los operadores == y =. Las comparaciones siempre se realizan con el operador ==, ya que el operador = solamente asigna valores. La condición que controla el if() puede combinar los diferentes operadores lógicos y relacionales mostrados anteriormente: var mostrado = false; if(!mostrado) { alert("Es la primera vez que se muestra el mensaje"); } Los operadores AND y OR permiten encadenar varias condiciones simples para construir condiciones complejas: var mostrado = false; var usuarioPermiteMensajes = true; if(!mostrado && usuarioPermiteMensajes) { alert("Es la primera vez que se muestra el mensaje"); } La condición anterior está formada por una operación AND sobre dos variables. A su vez, a la primera variable se le aplica el operador de negación antes de realizar 19 Juan Carlos Pérez González la operación AND. De esta forma, como el valor de mostrado es false, el valor ! mostrado sería true. Como la variable usuarioPermiteMensajes vale true, el resultado de !mostrado && usuarioPermiteMensajes sería igual a true && true, por lo que el resultado final de la condición del if() sería true y por tanto, se ejecutan las instrucciones que se encuentran dentro del bloque del if(). Ejercicio. Completar las condiciones de los if del siguiente script para que los mensajes de los alert() se muestren siempre de forma correcta: var numero1 = 5; var numero2 = 8; if(...) { alert("numero1 no es mayor que numero2"); } if(...) { alert("numero2 es positivo"); } if(...) { alert("numero1 es negativo o distinto de cero"); } if(...) { alert("Incrementar en 1 unidad el valor de numero1 no lo hace mayor o igual que numero2"); } • if...else En ocasiones, las decisiones que se deben realizar no son del tipo "si se cumple la condición, hazlo; si no se cumple, no hagas nada". Normalmente las condiciones suelen ser del tipo "si se cumple esta condición, hazlo; si no se cumple, haz esto otro". Para este segundo tipo de decisiones, existe una variante de la estructura if llamada if...else. Su definición formal es la siguiente: 20 Juan Carlos Pérez González if(condicion) { ... } else { ... } Si la condición es cierta (es decir, si su valor es true) se ejecutan las instrucciones que se encuentran dentro del if(). Si la condición no se cumple (es decir, si su valor es false) se ejecutan las instrucciones contenidas en else { }. var edad = 18; if(edad >= 18) { alert("Eres mayor de edad"); } else { alert("Todavía eres menor de edad"); } Si el valor de la variable edad es mayor o igual que el valor numérico 18, la condición del if() se cumple y por tanto, se ejecutan sus instrucciones y se muestra el mensaje "Eres mayor de edad". Sin embargo, cuando el valor de la variable edad no es igual o mayor que 18, la condición del if() no se cumple, por lo que automáticamente se ejecutan todas las instrucciones del bloque else { }. En este caso, se mostraría el mensaje "Todavía eres menor de edad". El siguiente ejemplo compara variables de tipo cadena de texto: var nombre = ""; if(nombre == "") { alert("Aún no nos has dicho tu nombre"); } else { 21 Juan Carlos Pérez González alert("Hemos guardado tu nombre"); } En el ejemplo anterior, si la cadena de texto almacenada en la variable nombre es vacía (es decir, es igual a "") se muestra el mensaje definido en el if(). En otro caso, se muestra el mensaje definido en el bloque else { }. La estructura if...else se puede encadenar para realizar varias comprobaciones: if(edad < 12) { alert("Todavía eres muy pequeño"); } else if(edad < 19) { alert("Eres un adolescente"); } else if(edad < 35) { alert("Aun sigues siendo joven"); } else { alert("Piensa en cuidarte un poco más"); } No es obligatorio que la combinación de estructuras if...else acabe con la instrucción else, ya que puede terminar con una instrucción de tipo else if(). • switch Una sentencia switch permite a un programa evaluar una expresión e intentar encajar el valor de dicha expresión a una etiqueta de caso. Si se encuentra una coincidencia, el programa ejecuta la sentencia asociada. Una sentencia switch se describe como se muestra a continuación: switch (expresión) { case etiqueta_1: sentencias_1 22 Juan Carlos Pérez González [break;] case etiqueta_2: sentencias_2 [break;] ... default: sentencias_por_defecto [break;] } El programa primero busca una claúsula case con una etiqueta que coincida con el valor de la expresión y, entonces, transfiere le control a esa cláusula, ejecutando las sentencias asociadas a ella. Si no se encuentran etiquetas coincidentes, el programa busca la cláusula opcional default y, si se encuentra, transfiere el control a esa cláusula, ejecutando las sentencias asociadas. Si no se encuentra la cláusula default, el programa continúa su ejecución por la siguiente sentencia al final del switch. Por convención, la cláusula por defecto es la última cláusula, aunque no es necesario que sea así. La sentencia opcional break asociada con cada cláusula case asegura que el programa finaliza la sentencia switch una vez que la sentencia asociada a la etiqueta coincidente es ejecutada y continúa la ejecución por las sentencias siguientes a la sentencia switch. Si se omite la sentencia break, el programa continúa su ejecución por la siguiente sentencia que haya en la sentencia switch. Ejemplo. En el siguiente ejemplo, si tipoFruta se evalúa como "Plátanos", el programa encaja el valor con el caso "Plátanos" y ejecuta las sentencias asociadas. Cuando se encuentra la sentencia break, el programa termina el switch y ejecuta las sentencias que le siguen. Si la sentencia break fuese omitida, la sentencia para el caso "Cerezas" también sería ejecutada. switch (tipoFruta) { case "Naranjas": console.log("Naranjas cuestan 0,59€ el kilo."); 23 Juan Carlos Pérez González break; case "Manzanas": console.log("Manzanas cuestan 0,32€ el kilo."); break; case "Plátanos": console.log("Plátanos cuestan 0,48€ el kilo."); break; case "Cerezas": console.log("Cerezas cuestan 3,00€ el kilo."); break; case "Mangos": console.log("Mangos cuestan 0,56€ el kilo."); break; case "Papayas": console.log("Mangos y papayas cuestan 2,79€ el kilo."); break; default: console.log("Disculpa, no tenemos el tipo de fruta " + fruittype + "."); } console.log("¿Te gustaría tomar algo?"); • Sentencias de manejo de excepciones Puedes lanzar excepciones usando la sentencia throw y manejarlas usando las sentencias try...catch. Tipos de excepciones Prácticamente cualquier objecto puede ser lanzado en JS. Sin embargo, no todos los objetos lanzados son creados igual. • Sentencia throw Utiliza la sentencia throw para lanzar una excepción. Cuando lanzas un 24 Juan Carlos Pérez González excepción, se especifica la expresión que contiene el valor para ser lanzado: throw expresión; Puedes lanzar cualquier expresión, no solo espresiones de un tipo espacifico. En el siguente código lanzamos varias excepciones de varios tipos: throw "Error2"; // Tipo string throw 42; // Tipo número throw true; // Tipo booleano throw {toString: function() { return "¡Soy un objeto!"; } }; En el siguiente ejemplo se crea un objeto myUserException del tipo UserException y lo usa en la sentencia throw. // Crear un tipo de objeto UserException function UserException (aviso){ this.aviso=aviso; this.nombre="UserException"; } // Make the exception convert to a pretty string when used as a string // (e.g. by the error console) UserException.prototype.toString = function () { return this.nombre + ': "' + this.aviso + '"'; } // Create an instance of the object type and throw it throw new UserException("Value too high"); • try...catch La sentencia try...catch marca un bloque de instrucciones a intentar que pueden causar alguna excepción, y declarar una o más respuestas en caso de que una excepción sea arrojada. Si una excepción es arrojada, la sentencia try...catch se encarga de atraparla. La sentencia try...catch consiste en un bloque try, el cuál contiene una o más instrucciones, y ninguno o varios bloques catch, conteniendo sentencias que 25 Juan Carlos Pérez González especifican que hacer si una excepción es arrojada en un bloque try. Se desea que las instrucciones dentro del bloque try se ejecuten con éxito, de caso contrario caerán en el bloque catch para ser controladas. Si ninguna instrucción dentro del bloque try (o en una función llamada dentro del bloque try) arroja una excepción, el control pasa inmediatamente al bloque catch. Si ninguna excepción es arrojada en el bloque try, el bloque catch es ignorado. Por último se ejecuta el bloque finally luego de que los bloques try y catch hayan sido ejecutados pero antes de las instrucciones que se encuentren luego de la sentencia try...catch. Ejemplo. El ejemplo llama a una función que retorna el nombre de un mes desde un arreglo basado en un valor pasado como argumento a la función. Si el valor no corresponde con el número de un mes (entre 1 y 12), una excepción es arrojada con el valor "InvalidMonthNo" y las instrucciones en el bloque catch le asignarán a la variable monthName el valor de unknown. function getMonthName (mo) { mo = mo-1; // Ajusta el indice del arreglo para el arreglo de meses (1=Jan, 12=Dec) var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec"]; if (months[mo] != null) { return months[mo]; } else { throw "InvalidMonthNo"; //Arroja la palabra "InvalidMonthNo" al ocurrir una excepción } } try { // instrucciones a probar monthName = getMonthName(myMonth); // La función puede arrojar una excepción } catch (e) { monthName = "unknown"; 26 Juan Carlos Pérez González logMyErrors(e); // Pasa el objeto de la excepción a un manejador de errores } • El bloque catch Un bloque catch es usado para manejar todas las excepciones que pueden ser generadas en el bloque try. catch (catchID) { instrucciones } El bloque catch especifica un identificar (catchID en la sintaxis anterior) que mantiene el valor especificado por la sentencia thrown; puedes usar este identificador para obtener información acerca de la excepción que fue arrojada. JS crea este identificador cuando ha entrado en el bloque catch; el identificador dura mientras dure el bloque catch; después de que el bloque catch termine su ejecución, el identificador ya no está disponible. Por ejemplo, el siguiente código arroja una excepción. Cuando la excepción ocurre, el control es transferido al bloque catch. try { throw "myException" // genera una excepción } catch (e) { // instrucciones para manejar cualquier excepción generada logMyErrors(e) // Pasa el objeto de excepción a un manejador de errores } • bloque finally El bloque finally contiene instrucciones para ejecutar luego de la ejecución del bloque try y el bloque catch pero antes de las instrucciones ubicadas luego de la sentencia try...catch. El bloque finally se ejecuta se haya arrojado o no una excepción. Si una excepción es arrojada, las instrucciones en el bloque finally se 27 Juan Carlos Pérez González ejecutan incluso si no existe un bloque catch que maneje la excepción. Se puede usar el bloque finally para hacer que tu script falle con gracia cuando una excepción ocurre; por ejemplo, puedes tener la necesidad de liberar un recurso que tu script tiene ocupado. Ejemplo. El siguiente ejemplo abre un archivo y luego ejecuta instrucciones que usan el archivo (JS del lado del servidor permite acceder a archivos). Si una excepción es arrojada mientras el archivo está abierto, el bloque finally cierra el archivo antes de que el script falle. openMyFile(); try { writeMyFile(theData); // Esto puede arrojar un error } catch(e) { handleError(e); // Si ocurre un error es manejado } finally { closeMyFile(); // Siempre cierra el recurso } Si el bloque finally retorna un valor, este valor se convierte en el valor de retorno de toda la sentencia try-catch-finally, independientemente de cualquier sentencia return en el bloque try y el bloque catch: function f() { try { console.log(0); throw "bogus"; } catch(e) { console.log(1); return true; // Esta sentencia de retorno es suspendida // hasta que el bloque finally esté completo console.log(2); // no alcanzable } finally { console.log(3); 28 Juan Carlos Pérez González return false; // sobreescribe la sentencia de retorno anterior console.log(4); // no alcanzable } // "return false" es ejecutada ahora console.log(5); // no alcanzable } f(); // console 0, 1, 3; retorna false Sobreescribiendo los valores retornados por el bloque finally también aplica a excepciones arrojadas o relanzadas dentro de un bloque catch: function f() { try { throw "bogus"; } catch(e) { console.log('caught inner "bogus"'); throw e; // Esta sentencia throw es suspendida hasta que // el bloque finally se termine de ejecutar } finally { return false; // Sobreescribe la sentencia throw anterior } // "return false" es ejecutado ahora } try { f(); } catch(e) { // Esta nunca es encontrada porque la sentencia throw dentro // del bloque catch es sobrescrita por la sentencia return // en el bloque finally console.log('caught outer "bogus"'); } 29 Juan Carlos Pérez González // SALIDA // atrapado dentro de "bogus" • Sentencias try...catch anidadas Es posible anidad una o más sentencias try...catch. Si una sentencia try...catch interna no posee un bloque catch, la sentencia try...catch exterior verifica si el bloque exterior genera una coincidencia. • Utilizando objetos de Error Dependiendo del tipo de error, es posible usar el 'name' (nombre) y el 'message' (mensaje) propiedades para obtener un mensaje más refinado. La propiedad 'name' provee la clase general del Error(por ejemplo, 'DOMException' or 'Error'), mientras que la propiedad 'message' por lo general provee un breve mensaje que puede ser obtenido convirtiendo el error de object a string. Si estás arrojando tus propias excepciones, en orden para tomar ventaja de estas propiedades (Como si tu bloque catch no discrimina entre tus propias excepciones y las excepciones del sistema), puedes usar el constructor de Error. Por ejemplo: function doSomethingErrorProne () { if (ourCodeMakesAMistake()) { throw (new Error('The message')); } else { doSomethingToGetAJSError(); } } .... try { doSomethingErrorProne(); } catch (e) { console.log(e.name); // logs 'Error' console.log(e.message); // logs 'The message' o un error de JS) 30 Juan Carlos Pérez González } • for Las estructuras if y if...else no son muy eficientes cuando se desea ejecutar de forma repetitiva una instrucción. Por ejemplo, si se quiere mostrar un mensaje cinco veces, se podría pensar en utilizar el siguiente if: var veces = 0; if(veces < 4) { alert("Mensaje"); veces++; } Sin embargo, el funcionamiento real del script anterior es muy diferente al deseado, ya que solamente se muestra una vez el mensaje por pantalla. La razón es que la ejecución de la estructura if() no se repite y la comprobación de la condición sólo se realiza una vez, independientemente de que dentro del if() se modifique el valor de la variable utilizada en la condición. La estructura for permite realizar este tipo de repeticiones (también llamadas bucles) de una forma muy sencilla. No obstante, su definición formal no es tan sencilla como la de if(): for(inicializacion; condicion; actualizacion) { ... } La idea del funcionamiento de un bucle for es la siguiente: "mientras la condición indicada se siga cumpliendo, repite la ejecución de las instrucciones definidas dentro del for. Además, después de cada repetición, actualiza el valor de las variables que se utilizan en la condición". • La "inicialización" es la zona en la que se establece los valores iniciales de las variables que controlan la repetición. • La "condición" es el único elemento que decide si continua o se detiene la 31 Juan Carlos Pérez González repetición. • La "actualización" es el nuevo valor que se asigna después de cada repetición a las variables que controlan la repetición. var mensaje = "Hola, estoy dentro de un bucle"; for(var i = 0; i < 5; i++) { alert(mensaje); } //La parte de la inicialización del bucle consiste en: var i = 0; Por tanto, en primer lugar se crea la variable i y se le asigna el valor de 0. Esta zona de inicialización solamente se tiene en consideración justo antes de comenzar a ejecutar el bucle. Las siguientes repeticiones no tienen en cuenta esta parte de inicialización. La zona de condición del bucle es: i<5 Los bucles se siguen ejecutando mientras se cumplan las condiciones y se dejan de ejecutar justo después de comprobar que la condición no se cumple. En este caso, mientras la variable i valga menos de 5 el bucle se ejecuta indefinidamente. Obviamente es imprescindible indicar la zona de actualización, en la que se modifica el valor de las variables que controlan el bucle: i++ En este caso, el valor de la variable i se incrementa en una unidad después de cada repetición. Normalmente, la variable que controla los bucles for se llama i, ya que recuerda a la palabra índice y su nombre tan corto ahorra mucho tiempo y espacio. Ejercicio. Mostrar los días de la semana contenidos en un array se puede rehacer de forma más sencilla utilizando la estructura for: 32 Juan Carlos Pérez González var dias = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"]; for(var i=0; i<7; i++) { alert(dias[i]); } • for...in Una estructura de control derivada de for es la estructura for...in. Su definición exacta implica el uso de objetos, que es un elemento de programación avanzada. Por tanto, solamente se va a presentar la estructura for...in adaptada a su uso en arrays. Su definición formal adaptada a los arrays es: for(indice in array) { ... } Si se quieren recorrer todos los elementos que forman un array, la estructura for...in es la forma más eficiente de hacerlo, como se muestra en el siguiente ejemplo: var dias = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"]; for(i in dias) { alert(dias[i]); } La variable que se indica como indice es la que se puede utilizar dentro del bucle for...in para acceder a los elementos del array. De esta forma, en la primera repetición del bucle la variable i vale 0 y en la última vale 6. Esta estructura de control es la más adecuada para recorrer arrays (y objetos), ya que evita tener que indicar la inicialización y las condiciones del bucle for simple y funciona correctamente cualquiera que sea la longitud del array. De hecho, sigue funcionando igual aunque varíe el número de elementos del array. 33 Juan Carlos Pérez González • for...of (This is a new technology, part of the ECMAScript 2015 (ES6) standard.) La sentencia for … of crea un bucle iterando sobre objeto iterables (incluyendo array, set, argumentos, objetos...), invocando una iteración personalizada conectando con sentencias para ser ejecutadas por le valor de cada propiedad distinta. for (variable de objeto) { sentencia } Ejemplo. Muestra la diferencia entre un bucle for...of y un bucle for...in . Mientras for...in itera sobre nombres de propiedades, for...of itera sobre valores de propiedades: let arr = [3, 5, 7]; /* let declara una variable de alcance local, la cual, opcionalmente, puede ser inicializada con algún valor.*/ arr.foo = "hello"; for (let i in arr) { console.log(i); // logs "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // logs "3", "5", "7" } • do...while. Esta sentencia repite hasta que una condición especificada se evalúa a false. Una sentencia do...while se mostrará como sigue: do …. while (condicion); Las sentencias se ejecutan antes de que la condición sea evaluada. Para ejecutar múltiples sentencias, use un bloque de sentencias ({ ... }) para agruparlas. Si la 34 Juan Carlos Pérez González condición es true, la sentencia se ejecuta de nuevo. Al final de cada ejecución, la condición es comprobada. Cuando la condición es falsa, la ejecución se detiene y el control pasa a la sentencia siguiente tras el bucle. Ejemplo. En el siguiente ejemplo, el bucle do itera al menos una vez y vuelve a hacerlo mientras i sea menor que 5. do { i += 1; console.log(i); } while (i < 5); • while Ejecuta sus sentencias mientras la condición sea evaluada como verdadera. Una sentencia while tiene el siguiente aspecto: while (condicion) sentencia Si la condición llega a ser falsa, la sentencia dentro del bucle se deja de ejecutarse y el control pasa a la sentencia inmediatamente después del bucle. La condición se evalúa antes de que la sentencia contenida en el bucle sea ejecutada. Si la condición devuelve verdadero, la sentencia se ejecuta y la condición se comprueba de nuevo. Si la condición es evaluada como falsa, se detiene la ejecución y el control pasa a la sentencia siguiente al while. Para múltiples sentencias, usamos el bloque de sentencias ({ ... }) para agruparlas. Ejemplo. El siguiente bucle while itera mientras n sea menor que tres: n = 0; x = 0; while (n < 3) { n++; x += n; } 35 Juan Carlos Pérez González • Después del primer paso: n = 1 y x = 1 • Después del segundo paso: n = 2 y x = 3 • Después del tercer paso: n = 3 y x = 6 • break La sentencia break permite salir de un bucle, switch, o en conjunto con una sentencia label. • Cuando usamos break sin un label, finaliza inmediatamente el código encerrado en while, do-while, for, o switch y transfiere el control a la siguiente sentencia. • Cuando usamos break con un label, termina la sentencia especificada por label. La sintaxis de la sentencia break es la siguiente: break; break label; La primera forma de la sintaxis finaliza con lo encerrado por el bucle o switch; la segunda finaliza lo especificado por la sentencia label. Ejemplo. El siguiente ejemplo itera a través de los elementos en un array hasta que encuentra que un índice de un elemento cuyo valor es elValor: for (i = 0; i < a.longitud; i++) { if (a[i] == elValor) { break; } } Ejemplo. Breaking a un label var x = 0; var z = 0 36 Juan Carlos Pérez González labelCancelLoops: while (true) { console.log("Outer loops: " + x); x += 1; z = 1; while (true) { console.log("Inner loops: " + z); z += 1; if (z ==10 && x == 10) { break labelCancelLoops; } else if (z == 10) { break; } } • continue Puede usarse para reiniciar una sentencia while, do-while, for, o label. Continue sin un label, termina la iteración en curso del código encerrado en una sentencia while, do-while, o for y continúa la ejecución del bucle con la siguiente iteración. A diferencia de la sentencia break, continue no termina completamente la ejecución del bucle. En un bucle while, salta atrás hasta la condición. En un bucle for, salta a la expresion Incremento. Cuando usamos continue con una etiqueta, esto se aplica a las sentencias anidadas identificadas con una etiqueta. La sintaxis de la sentencia continue es la siguiente: continue; continue label; 37 Juan Carlos Pérez González Ejemplo. El siguiente ejemplo muestra un bucle while con una sentencia continue que se ejecuta cuando el valor de i es tres. Así, n toma los valores uno, tres, siete, y doce. i = 0; n = 0; while (i < 5) { i++; if (i == 3) { continue; } n += i; } 7. Uso de contornos de desarrollo integrados Un IDE (Integrated Development Environment o Entorno de Desarrollo Integrado) nos ofrece muchas más funciones que un editor de texto, hay que tener en cuenta que soportan muchos tipos de lenguajes de programación y otra ventaja que poseen es que la mayoría son de tipo “open source”, esto es, de descarga gratuita. A continuación se muestran algunos de los ejemplos: • Aptana Studio: Aptana Studio es bastante simple en comparación con otras IDEs. Puede depurar sus JS usando Firefox + Firebug. También se puede obtener una vista previa en el navegador integrado (soporta IE, Firefox y Safari). Se puede usar Aptana como un plugin con Eclipse o puede descargar la versión autónoma de Aptana Studio. Soporta además múltiples lenguajes de servidor, como PHP, Python y Ruby on Rails • NetBeans: también tiene un gran soporte para la escritura de simple, así como JS compleja. Es un editor de código fuente con autocompletado y un depurador que se integra bien con Internet Explorer y Firefox. Será nuestra herramienta de trabajo. • WebStorm:WebStorm es una de las últimas IDEs para JS. Es ligero y tiene un editor de código JS y depurador. También puede integrar Firebug para depurar con Firefox. También tiene buen soporte para la escritura de HTML5 y al igual que 38 Juan Carlos Pérez González Aptana Studio se puede conectar a un servidor FTP para sincronizar los scripts. • Cloud 9: Un entorno en la nube, soporta muchos lenguajes y entre ellos JS. Hay una cuenta gratuita pero puedes optar a otras con diferentes costes. • Spket IDE: es otro ejemplo de IDE que funciona para el desarrollo del lenguaje JS y XML. • API for JS Sandbox: por supuesto no es una IDE como tal pero es está bien comentarlo sobre todo para las personas que empiezan a jugar con el código y familiarizándose con los ejemplos de código fuente que aporta ESRI en la web de la API. Te permite modificar dicho código de ejemplo y ver qué efecto tiene sobre el mapa. • Kompozer: editor de HTML y CSS que es gratuito y multiplataforma (Windows Mac y Linux). Ofrece vista previa de la página mientras se escribe código, múltiples pestañas, edición específica de CSS, etc. • Notepad++: Es gratuito y además Open Source aunque solo funciona bajo Windows. Dispone de multitud de plugins para extender su funcionalida. Va mucho más allá que el bloc de notas ya que ofrece sintaxis coloreada, estructuración de código (para poder plegar y desplegar zonas cubiertas por etiquetas), soporte de otros muchos lenguajes de programación, etc... Está bien tenerlo a mano para pruebas o ediciones rápidas. • BlueGriffon: Este excelente editor WYSIWYG utiliza por debajo el motor de renderizado de Firefox para visualizar las páginas a medida que las vamos editando. Cuenta con ayudas a la escritura de código (como las “miguitas de pan” de la parte de abajo o el acceso a la estructura jerárquica de la página), y ofrece incluso la posibilidad de probar en tiempo real transformaciones 3D de CSS3 sin abandonar el editor (ventajas de utilizar el motor Gecko de Mozilla). Es gratuito, Open Source y multiplataforma (Windows, Mac y Linux) y está disponible en Español entre otros muchos idiomas. La última versión es de hace casi un año, pero el proyecto sigue activo. • Sublime Text: Un editor de texto avanzado para programadores, multiplataforma. Aunque es bastante espartano lo cierto es que todo el que invierte tiempo en 39 Juan Carlos Pérez González aprender a dominarlo luego no lo quiere dejar, ya que aumenta mucho la productividad a la hora de escribir código. No ofrece muchas de las características de ayuda al programador web que sí ofrecen la mayoría de los otros entornos, por lo que es recomendable sobre todo si vamos a trabajar mucho directamente con código, especialmente JS. Lo podemos descargar y utilizar gratuitamente, pero si lo vamos a usar a menudo para trabajar sus creadores nos solicitan que les paguemos una licencia (es lo justo). Ésta tiene un precio muy razonable. • Microsoft VS Express for Web Está disponible en varios idiomas (incluyendo el Español) y su única limitación es que sólo funciona bajo Windows. Es decir, que si trabajas en Mac o Linux no podrás utilizarlo. Aunque, al igual que el anterior, es una herramienta técnica orientada a programadores y con muchas otras posibilidades avanzadas, ofrece un soporte estupendo para diseño de páginas Web, con editores avanzados de HTML, CSS y JS, capacidad de depuración, ayuda contextual para todos los lenguajes, validadores de código, validadores de accesibilidad, visualización real de cómo van a quedar las páginas, etc...Es totalmente gratuito. 8. Depuración e documentación do código. Las herramientas de desarrollo de los navegadores cada vez son más potentes y van mejorando día a día. El primer gran debugger de JavaScript fue Firebug para Firefox, pero actualmente tenemos las herramientas de desarrollo de Chrome y las de Internet Explorer (que han mejorado mucho en su versión número 11) como buena y completa competencia. Las APIs de la consola han evolucionado y encontramos cosas tan interesantes como tablas de datos en la consola, algo que ayuda mucho a visualizar, sobre todo, respuestas por parte de un servidor. Funciones básicas Desde hace tiempo la API básica que incorporan casi todas las herramientas de desarrollo de los navegadores permitía lanzar nuevos avisos de distintos tipos. Estas utilidades son esenciales cuando queremos depurar ciertas partes del código de una forma no intrusiva o monitorizar ciertos parámetros, aunque hay quien prefiere las alertas (alert()), que tienen 40 Juan Carlos Pérez González la ventaja de parar la ejecución. Los avisos básicos que se le puede mandar a una consola de depuración (y soportan casi todas las herramientas de debugging) son básicamente tres: • el de registro o log, • el de aviso • el de error. La función para crear un registro o una alerta son más o menos similares, pero la función de enviar un error hace un seguimiento de como se ha llegado hasta el propio error, como veremos a continuación. A la API de la consola se accede a través de console, que alberga distintos métodos para crear estas alertas (log(), warn() y error()). Estos métodos nos permiten enviarle texto o cualquier tipo de variable (ya sea un número, un objeto JSON, una función, un elemento del DOM...) y así poder visualizar cómodamente los datos extraídos del documento. Para probar los ejemplos debes de abrir la consola de depuración (pulsando F12). Mandar un log con un texto básico: // Texto console.log("Texto de prueba") Mandando un log con un objeto del DOM: // Objeto DOM console.log(this) Mandamos un log con texto y un objeto: // Texto y objetos console.log("Objeto de prueba:", {a:1, b:2, n:[1, 2, 3]}) Por último, para completar las acciones básicas limpiaremos la consola con console.clear(): // Limpiar consola console.clear() Funciona igual de igual forma los tres tipos de avisos, por lo que solo voy a poner un solo 41 Juan Carlos Pérez González ejemplo más de cada uno para ver la diferencia: Tablas en consola Recientemente se ha implementado en las principales herramientas de depuración (para ser exacto en Firebug y las de Chrome) la función de generar tablas a partir de un objeto o arrays bidimensionales, que nos facilita la visión de datos que se han podido generar o recibir. La imagen de arriba la genera la consola al usar console.table() enviando un objeto que perfectamente podríamos recibir desde un servidor: var WeblogsSL = [ {nombre: "Xataka", visitas: 300000, color: "Verde"}, {nombre: "Applesfera", visitas: 200000, color: "Gris"}, {nombre: "Genbeta", visitas: 220000, color: "Azul"} ]; console.table(WeblogsSL); Al igual que antes, podemos hacer lo mismo con un array bidimensional, que podría contener los datos de una gráfica, por poner un ejemplo: var grafica = [ [1048, 1083, 1127, 1154, 1215], [952, 977, 1109, 1063, 1054], [944, 944, 1008, 1073, 1073], [34, 40, 51, 56, 61], [1191, 1258, 1290, 1368, 1402], [542, 543, 571, 606, 630] 42 Juan Carlos Pérez González ]; console.table(grafica); En cuanto a la documentación del código JS hay multitud de herramientas pero nos centraremos en JSDoc. • JSDoc es una sintaxis para agregar documentación al código de JS.La sintaxis JSDoc es similar a la sintaxis de JavaDoc, usado para documentar el código de Java, pero se ha especializado para trabajar con la sintaxis de JavaScript, es más dinámico y, por tanto único, ya que no es totalmente compatible con Javadoc. 43 Juan Carlos Pérez González 44 Juan Carlos Pérez González Referencias: www.aprendeaprogramar.com https://developer.mozilla.org/es/docs/Web/JS/Guide www.campusmvp.es http://www.genbetadev.com 45