Aprendiendo PHP, MySQL y JavaScript



Prefacio

Audiencia



Introducción al contenido dinámico de la web

HTTP y HTML: Los conceptos básicos de Berners-Lee



Configuración de un servidor de desarrollo

¿Qué es WAMP, MAMP o LAMP?



Introducción a PHP

Integrando PHP dentro de HTML



Expresiones y control de flujo en PHP

Expresiones



Funciones y objetos en PHP

Funciones en PHP



Arrays en PHP

Acceso básico



PHP práctico

Utilizando printf



Introducción a MySQL

Fundamentos de MySQL



Dominando MySQL

Diseño de bases de datos



Novedades de PHP 8 y MySQL 8

Sobre este capítulo



Accediendo a MySQL utilizando PHP

Consultando una base de datos MySQL con PHP



Manejo de formularios

Creación de formularios



Cookies, sesiones y autenticación

Utilizando cookies en PHP



Explorando JavaScript

Introducción

JavaScript aporta una funcionalidad dinámica a tus sitios web. Cada vez que mires algo aparecer cuando pasas el mouse sobre un elemento en el navegador, o ves nuevo texto, colores o imágenes aparecer en la página frente a tus ojos, o cuando tomas un objeto en la página y lo arrastras a una nueva ubicación, todas esas cosas generalmente se hacen a través de JavaScript (aunque CSS se está volviendo cada vez más poderoso y también puede hacer muchas de estas cosas). Ofrece efectos que de otro modo no serían posibles, porque se ejecuta dentro del navegador y tiene acceso directo a todos los elementos de un documento web.

JavaScript apareció por primera vez en el navegador Netscape Navigator en 1995, coincidiendo con la incorporación del soporte para la tecnología Java en el navegador. Debido a la incorrecta impresión inicial de que JavaScript era un derivado de Java, ha habido una confusión durante mucho tiempo sobre su relación. Sin embargo, el nombre fue solo una táctica de marketing para ayudar al nuevo lenguaje de scripting a beneficiarse de la popularidad del lenguaje de programación Java.

JavaScript ganó nuevo poder cuando los elementos HTML de la página web obtuvieron una definición más formal y estructurada en lo que se llama Document Object Model (DOM). El DOM hace que sea relativamente fácil añadir un nuevo párrafo o centrarse en un fragmento de texto y modificarlo.

Debido a que tanto JavaScript como PHP soportan gran parte de la sintaxis de la programación estructurada que utiliza el lenguaje de programación C, son muy similares entre sí. También son lenguajes de alto nivel. Además, son débilmente tipados, por lo que es fácil cambiar una variable a un nuevo tipo simplemente usándola en un nuevo contexto.

Ahora que has aprendido PHP, deberías encontrar JavaScript aún más fácil. Y te alegrarás de haberlo hecho, porque está en el corazón de la tecnología de la comunicación asíncrona que proporciona las interfaces web fluidas que (junto con las características de HTML5) los usuarios web expertos esperan hoy en día.

Texto JavaScript y HTML

JavaScript es un lenguaje de scripting del lado del cliente que se ejecuta completamente dentro del navegador web o bajo Node.js. Para llamarlo, se coloca entre las etiquetas HTML de apertura <script> y cierre </script>. Un documento típico de "Hello World" utilizando JavaScript puede parecerse al Ejemplo 14-1.

Ejemplo 14-1. Visualización de "Hello World" con JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
<html> <head> <title>Hello World</title> </head> <body> <script type="text/javascript"> document.write("Hello World") </script> <noscript> Your browser doesn't support or has disabled JavaScript </noscript> </body> </html>

Nota

Es posible que hayas visto páginas web que utilizan la etiqueta HTML <script language="javascript">, pero ahora esa manera está obsoleta. Este ejemplo utiliza el más reciente y preferido <script type="text/javascript">, o puedes simplemente utilizar <script> por tu cuenta si lo prefieres.

Dentro de las etiquetas <script> hay una sola línea de código JavaScript que utiliza su equivalente a los comandos echo o print de PHP, es document.write. Como era de esperar, simplemente envía el string proporcionado al documento actual, donde se muestra.

También puede que haya notado que, a diferencia de PHP, no hay punto y coma al final (;). Esto se debe a que un salto de línea cumple la misma función que un punto y coma en JavaScript. Sin embargo, si deseas tener más de una instrucción en una sola línea, debes colocar un punto y coma después de cada comando, excepto el último. Por supuesto, si lo deseas, puedes añadir un punto y coma al final de cada instrucción, y tu JavaScript funcionará bien. Mi preferencia personal es omitir el punto y coma porque es innecesario, y por lo tanto también evito prácticas que podrían causar problemas. Al final del día, sin embargo, la elección puede depender del equipo en el que trabajes, que más a menudo no puede requerir puntos y coma, solo para estar seguros. Entonces, si tienes dudas, simplemente añade los puntos y comas.

Lo otro a tener en cuenta en este ejemplo es el par de etiquetas <noscript> y </noscript>. Estos se utilizan cuando deseas ofrecer HTML alternativo a los usuarios cuyos navegadores no soportan JavaScript o lo tienen desactivado. El uso de estas etiquetas depende de ti, ya que no son obligatorias, pero realmente deberías usarlas porque generalmente no es tan difícil proporcionar alternativas HTML estáticas a las operaciones que ofreces utilizando JavaScript. Sin embargo, los ejemplos restantes en este libro omitirán las etiquetas <noscript>, porque nos estamos enfocando en lo que puedes hacer con JavaScript, no en lo que puedes hacer sin él.

Cuando se carga el Ejemplo 14-1, un navegador web con JavaScript habilitado mostrará lo siguiente (ver Figura 14-1):

Hello World
figura_14-1.png
Figura 14-1. JavaScript, habilitado y funcionando

Un navegador con JavaScript desactivado mostrará este mensaje (ver Figura 14-2):

Your browser doesn't support or has disabled JavaScript
figura_14-2.png
Figura 14-2. JavaScript, desactivado

Uso de scripts dentro de la cabecera de un documento

Además de colocar un script dentro del cuerpo de un documento, puedes ponerlo en la sección <head>, que es el lugar ideal si deseas ejecutar un script cuando se carga una página. Si colocas código y funciones críticas allí, también puedes tener la seguridad de que estén listos para usarse de inmediato por cualquier otra sección de script en el documento que dependa de ellos.

Otra razón para colocar un script en la cabecera del documento es permitir que JavaScript escriba cosas como meta etiquetas en la sección <head>, porque la ubicación de tu script es la parte del documento donde se escribe (imprime) por defecto.

Navegadores antiguos y no estándar

Si necesitas soportar navegadores que no ofrecen scripting (muy poco probable en la actualidad), deberás usar las etiquetas de comentario HTML (<!-- y -->) para evitar que se encuentren con código script que no deberían ver. El ejemplo 14-2 muestra cómo añadirlos a tu código de script.

Ejemplo 14-2. El ejemplo de "Hello World" modificado para navegadores que no soportan JavaScript

1
2
3
4
5
6
7
8
9
10
11
<html> <head> <title>Hello World</title> </head> <body> <script type="text/javascript"><!-- document.write('Hello World') // --> </script> </body> </html>

Aquí se ha añadido una etiqueta HTML de apertura de comentario (<!--) directamente después de la declaración de apertura <script>, y se ha añadido una etiqueta de cierre de comentario (// -->) directamente antes de que el script se cierre con </script>.

La doble barra diagonal (//) la utiliza JavaScript para indicar que el resto de la línea es un comentario. Está ahí para que los navegadores que sí soportan JavaScript ignoren el siguiente -->, pero los navegadores que no soportan JavaScript ignorarán el // anterior y actuarán sobre el --> cerrando el comentario HTML.

Aunque la solución es un poco complicada, lo único que realmente necesitas recordar es utilizar las dos líneas siguientes para encerrar tu JavaScript cuando desees soportar navegadores muy antiguos o no estándar:

1
2
3
4
<script type="text/javascript"><!-- (Your JavaScript goes here...) // --> </script>

Sin embargo, el uso de estos comentarios es innecesario para cualquier navegador lanzado en los últimos años, pero debes estar al tanto de esto, por si acaso.

Incluyendo archivos JavaScript

Además de escribir código JavaScript directamente en documentos HTML, puedes incluir archivos de código JavaScript desde tu sitio web o desde cualquier lugar de internet. La sintaxis para esto es la siguiente:

1
<script type="text/javascript" src="script.js"></script>

O, para cargar un archivo desde internet, usa esto (aquí sin el type="text/javascript" ya que es opcional):

1
<script src="http://someserver.com/script.js"></script>

En cuanto a los archivos de script en sí, no deben incluir ninguna etiqueta <script> o </script>, porque son innecesarias: el navegador ya sabe que se está cargando un archivo JavaScript. Ponerlos en los archivos JavaScript causará un error.

Incluir archivos de script es la forma preferida para que uses archivos JavaScript de terceros en tu sitio web.

Nota

Es posible omitir el parámetro type="text/javascript"; todos los navegadores modernos asumen por defecto que el script contiene JavaScript.

Depuración de errores en JavaScript

Cuando estás aprendiendo JavaScript, es importante poder rastrear errores de escritura u otros errores de codificación. A diferencia de PHP, que muestra mensajes de error en el navegador, JavaScript maneja los mensajes de error de una manera que cambia de acuerdo con el navegador que se esté utilizando. La Tabla 14-1 muestra cómo acceder a los mensajes de error de JavaScript en los navegadores más utilizados.

Tabla 14-1. Acceso a los mensajes de error de JavaScript en diferentes navegadores

Navegador Cómo acceder a los mensajes de error de JavaScript
Apple Safari Abre Safari y elige Safari > Preferencias > Avanzado. Luego selecciona Mostrar menú de desarrollo en la barra de menú. Elige Desarrollar > Mostrar Consola de Errores
Google Chrome, Microsoft Edge, Mozilla Firefox, & Opera Presiona Ctrl + Shift + J en una PC o Command + Shift + J en una Mac.

Por favor, consulte la documentación de los desarrolladores del navegador en sus sitios web para obtener todos los detalles sobre su uso.

Utilizando comentarios

Debido a su herencia compartida del lenguaje de programación C, PHP y JavaScript tienen muchas similitudes, una de las cuales es la forma de comentar. Primero, hay el comentario de una sola línea, como este:

1
// This is a comment

Este estilo utiliza un par de caracteres de barra diagonal (//) para informar a JavaScript que todo lo que sigue debe ser ignorado. También tienes comentarios multilínea, como este:

1
2
3
4
/* This is a section of multiline comments that will not be interpreted */

Empiezas un comentario de varias líneas con la secuencia /* y lo terminas con */. Solo recuerda que no puedes anidar comentarios multilínea, así que asegúrate de no comentar grandes secciones de código que ya contengan comentarios multilínea.

Signos de punto y coma

A diferencia de PHP, JavaScript generalmente no requiere punto y coma si tienes solo una instrucción en una línea. Por lo tanto, lo siguiente es válido:

1
x += 10

Sin embargo, cuando desees colocar más de una declaración en una línea, debes separarlas con punto y coma, así:

1
x += 10; y -= 5; z = 0

Normalmente puedes omitir el punto y coma final, porque la nueva línea termina la declaración final.

Precaución

Hay excepciones a la regla del punto y coma. Si escribes bookmarklets (marcadores) en JavaScript, o terminas una declaración con una referencia a una variable o función, y el primer carácter de la siguiente línea es un paréntesis izquierdo o un corchete, debes recordar agregar un punto y coma o JavaScript fallará. Entonces, cuando tengas dudas, usa un punto y coma.

Variables

Ningún carácter en particular identifica una variable en JavaScript como lo hace el signo de dólar en PHP. En su lugar, las variables utilizan las siguientes reglas de nomenclatura:

  • Una variable puede incluir solo las letras a–z, A–Z, 0–9, el símbolo $ y el guion bajo (_).
  • No se permiten otros caracteres, como espacios o signos de puntuación, en el nombre de una variable.
  • El primer carácter del nombre de una variable puede ser solo a–z, A–Z, $, o _ (sin números).
  • Los nombres son sensibles a mayúsculas y minúsculas. Count, count y COUNT son todas variables diferentes.
  • No hay un límite establecido para la longitud de los nombres de las variables.

Y sí, tienes razón: hay un $ en esta lista de caracteres permitidos. Está permitido por JavaScript y puede ser el primer carácter de un nombre de una variable o función. Aunque no recomiendo utilizar los caracteres $, esta regla te permite integrar mucho código PHP más rápidamente a JavaScript.

Variables string

Las variables string en JavaScript deben estar entre comillas simples o dobles, así:

1
2
greeting = "Hello there" warning = 'Be careful'

Puedes incluir una comilla simple dentro de un string de comillas dobles o una comilla doble dentro de un string de comillas simples. Pero debes escapar el entrecomillado del mismo tipo usando el carácter de barra invertida, así:

1
2
greeting = "\"Hello there\" is a greeting" warning = '\'Be careful\' is a warning'

Para leer de una variable string, puedes asignarla a otra, así:

1
newstring = oldstring

o puedes usarla en una función, así:

1
2
status = "All systems are working" document.write(status)

Variables numéricas

Crear una variable numérica es tan simple como asignarle un valor, como estos ejemplos:

1
2
count = 42 temperature = 98.4

Al igual que los strings, las variables numéricas pueden leerse y usarse en expresiones y funciones.

Arrays

Los arrays en JavaScript también son muy similares a los de PHP, en el sentido de que un array puede contener datos de tipo string o numéricos, así como otros arrays. Para asignar valores a un array, utiliza la siguiente sintaxis (que en este caso crea un array de strings):

1
toys = ['bat', 'ball', 'whistle', 'puzzle', 'doll']

Para crear un array multidimensional, anida arrays más pequeños dentro de uno más grande. Entonces, para crear un array bidimensional que contenga los colores de una sola cara de un Cubo Rubik desordenado (donde los colores red (rojo), green (verde), orange (naranja), yellow (amarillo), blue (azul) y white (blanco) están representados por sus letras iniciales en mayúscula), podrías usar el siguiente código:

1
2
3
4
5
face = [ ['R', 'G', 'Y'], ['W', 'R', 'O'], ['Y', 'W', 'G'] ]

El ejemplo anterior se le ha dado formato para que sea obvio lo que está sucediendo, pero también podría escribirse así:

1
face = [['R', 'G', 'Y'], ['W', 'R', 'O'], ['Y', 'W', 'G']]

o incluso así:

1
2
3
4
5
top = ['R', 'G', 'Y'] mid = ['W', 'R', 'O'] bot = ['Y', 'W', 'G'] face = [top, mid, bot]

Para acceder al elemento dos hacia abajo y tres hacia la derecha en este array, usarías lo siguiente (porque los elementos del array comienzan en la posición 0):

1
document.write(face[1][2])

Esta declaración mostrará la letra O para orange (naranja).

Nota

Los arrays en JavaScript son estructuras de almacenamiento poderosas, por lo que en el Capítulo 16 se tratan con mucho más detalle.

Operadores

Los operadores en JavaScript, al igual que en PHP, pueden incluir matemáticas, cambios en strings y operaciones de comparación y lógicas. (and, or, etc.). Los operadores matemáticos de JavaScript se parecen mucho a la aritmética básica; por ejemplo, la siguiente instrucción devuelve 15:

1
document.write(13 + 2)

Las siguientes secciones te enseñan sobre los distintos operadores.

Operadores aritméticos

Los operadores aritméticos se utilizan para realizar operaciones matemáticas. Puedes usarlos para las cuatro operaciones principales (suma, resta, multiplicación y división), así como para encontrar el módulo de una división (el residuo después de una división) y para incrementar o decrementar un valor. (ver la Tabla 14-2).

Tabla 14-2. Operadores aritméticos

Operador Descripción Ejemplo
+ Suma j + 12
- Resta j - 22
* Multiplicación j * 7
/ División j / 3.13
% Módulo (resto de la división) j % 6
++ Incremento ++j
-- Decremento --j

Operadores de asignación

Los operadores de asignación se utilizan para asignar valores a las variables. Empiezan con el muy simple = y continúan con +=, –=, y así sucesivamente. El operador += añade el valor del lado derecho a la variable del lado izquierdo, en lugar de reemplazar totalmente el valor del lado izquierdo. Así, si count comienza con el valor de 6, la declaración:

1
count += 1

establece count en 7, al igual que la declaración de asignación más familiar:

1
count = count + 1

La Tabla 14-3 enumera los distintos operadores de asignación disponibles.

Tabla 14-3. Operadores de asignación

Operador Ejemplo Equivalente a
= j = 99 j = 99
+= j += 2 j = j + 2
+= j += 'string' j = j + 'string'
–= j –= 12 j = j – 12
*= j *= 2 j = j * 2
/= j /= 6 j = j / 6
%= j %= 7 j = j % 7

Operadores de comparación

Los operadores de comparación se utilizan generalmente dentro de una estructura como en una declaración if, donde necesitas comparar dos elementos. Por ejemplo, puede que desees saber si una variable que se ha estado incrementando ha alcanzado un valor específico, o si otra variable es menor que un valor establecido, y así sucesivamente. (ver la Tabla 14-4).

Tabla 14-4. Operadores de comparación

Operador Descripción Ejemplo
== Es igual a j == 42
!= No es igual a j != 17
> Es mayor que j > 0
< Es menor que j < 100
>= Es mayor o igual que j >= 23
<= Es menor o igual que j <= 13
=== Es igual a (y del mismo tipo) j === 56
!== No es igual a (y del mismo tipo) j !== '1'

Operadores lógicos

A diferencia de PHP, los operadores lógicos de JavaScript no incluyen equivalentes de and y or a && y ||, y no hay un operador xor. (ver la Tabla 14-5).

Tabla 14-5. Operadores lógicos

Operador Descripción Ejemplo
&& And j == 1 && k == 2
|| Or j < 100 || j > 0
! Not ! (j == k)

Incrementando, decrementando y asignación abreviada

Las siguientes formas de post y preincremento y decremento que aprendiste a utilizar en PHP también son compatibles con JavaScript, al igual que los operadores de asignación abreviada:

1
2
3
4
++x --y x += 22 y -= 3

Concatenación de strings

JavaScript maneja la concatenación de strings de manera ligeramente diferente a PHP. En lugar del operador . (punto), utiliza el signo más (+), así:

1
document.write("You have " + messages + " messages.")

Suponiendo que la variable messages está establecida con el valor de 3, la salida de esta línea de código será la siguiente:

You have 3 messages.

Así como puedes agregar un valor a una variable numérica con el operador +=, también puedes concatenar un string a otra de la misma manera:

1
2
name = "James" name += " Dean"

Caracteres de escape

Los caracteres de escape, que se han utilizado para insertar comillas en los strings, también pueden ser utilizados para insertar varios caracteres especiales, como tabulaciones, saltos de línea y retornos de carro. Aquí hay un ejemplo usando tabulaciones para organizar un encabezado: se incluye aquí simplemente para ilustrar escapes, porque en las páginas web, hay mejores maneras de hacer el diseño:

1
heading = "Name\tAge\tLocation"

La Tabla 14-6 detalla los caracteres de escape disponibles.

Tabla 14-6. Caracteres de escape en JavaScript

Caracter Significado
\b Retroceso
\f Salto de página
\n Salto de línea
\r Retorno de carro
\t Tabulador
\' Comillas simples (o apóstrofe)
\" Comillas dobles
\\ Barra invertida
\XXX Un número octal entre 000 y 377 que representa el equivalente de caracteres Latin-1 (como \251 para el símbolo ©)
\xXX Un número hexadecimal entre 00 y FF que representa el equivalente de caracteres Latin-1 (como \xA9 para el símbolo ©)
\uXXXX Un número hexadecimal entre 0000 y FFFF que representa el equivalente de caracteres Unicode (como \u00A9 para el símbolo ©)

Tipado de variables

Al igual que PHP, JavaScript es un lenguaje muy débilmente tipado; el tipo de dato de una variable se determina solo cuando se le asigna un valor y puede cambiar a medida que la variable aparece en diferentes contextos. Por lo general, no tienes que preocuparte por el tipo de dato de las variables; JavaScript averigua lo que quieres y simplemente lo hace.

Echa un vistazo al Ejemplo 14-3, en el cual:

  1. A la variable n se le asigna el valor del string '838102050'. La siguiente línea imprime su valor, y se utiliza el operador typeof para consultar el tipo de dato de la variable.
  2. n se le asigna el valor devuelto cuando se multiplican los números 12345 y 67890. Este valor también es 838102050, pero es un número, no un string. El tipo de dato de la variable se busca y se muestra.
  3. Se añade algún texto al número n y se muestra el resultado.

Ejemplo 14-3. Establece el tipo de dato de una variable por asignación

1
2
3
4
5
6
7
8
9
10
<script> n = '838102050' // Set 'n' to a string document.write('n = ' + n + ', and is a ' + typeof n + '<br>') n = 12345 * 67890; // Set 'n' to a number document.write('n = ' + n + ', and is a ' + typeof n + '<br>') n += ' plus some text' // Change 'n' from a number to a string document.write('n = ' + n + ', and is a ' + typeof n + '<br>') </script>

La salida de este script se ve así:

n = 838102050, and is a string
n = 838102050, and is a number
n = 838102050 plus some text, and is a string

Si alguna vez hay alguna duda sobre el tipo de dato de una variable, o necesitas asegurarte de que una variable tenga un tipo de dato en particular, puedes forzarla a ese tipo de dato utilizando declaraciones como las siguientes (que convierten respectivamente un string a un número y un número a un string):

1
2
3
4
5
n = "123" n *= 1 // Convert 'n' into a number n = 123 n += "" // Convert 'n' into a string

O puedes usar las siguientes funciones de la misma manera:

1
2
3
4
5
6
n = "123" n = parseInt(n) // Convert 'n' into an integer number n = parseFloat(n) // Convert 'n' into a floating point number n = 123 n = n.toString() // Convert 'n' into a string

Puedes leer más sobre la conversión de tipos de datos en JavaScript en línea (https://es.javascript.info/type-conversions). Y siempre puedes consultar el tipo de dato de una variable usando el operador typeof.

Funciones

Al igual que con PHP, las funciones en JavaScript se utilizan para separar secciones de código que realizan una tarea específica. Para crear una función, se declara de la manera que se muestra en el Ejemplo 14-4.

Ejemplo 14-4. Una declaración simple de una función

1
2
3
4
5
6
<script> function product(a, b) { return a*b } </script>

Esta función toma los dos parámetros pasados, los multiplica y devuelve el resultado.

Variables globales

Las variables globales son aquellas definidas fuera de cualquier función (o definidas dentro de funciones pero sin la palabra clave var). Pueden definirse de las siguientes maneras:

1
2
3
a = 123 // Global scope var b = 456 // Global scope if (a == 123) var c = 789 // Global scope

Independientemente si estás utilizando la palabra clave var, mientras una variable esté definida fuera de una función, su alcance es global. Esto significa que cada parte de un script puede tener acceso a él.

Variables locales

Los parámetros pasados a una función automáticamente tienen un alcance local, es decir, solo pueden ser referenciados dentro de esa función. Sin embargo, hay una excepción. Los arrays se pasan a una función por referencia, por lo que si modificas cualquier elemento de un parámetro de tipo array, los elementos del array original serán modificados.

Para definir una variable local que tenga alcance solo dentro de la función actual y que no haya sido pasada como parámetro, utiliza la palabra clave var. El Ejemplo 14-5 muestra una función que crea una variable con alcance global y dos con alcance local.

Ejemplo 14-5. Una función que crea variables con alcance global y local

1
2
3
4
5
6
7
8
<script> function test() { a = 123 // Global scope var b = 456 // Local scope if (a == 123) var c = 789 // Local scope } </script>

Para comprobar si la configuración del alcance ha funcionado en PHP, podemos usar la función isset. Pero en JavaScript no existe tal función, así que el Ejemplo 14-6 utiliza el operador typeof, que devuelve el string undefined cuando una variable no está definida.

Ejemplo 14-6. Verificación del alcance de las variables definidas en la función test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script> test() if (typeof a != 'undefined') document.write('a = "' + a + '"<br>') if (typeof b != 'undefined') document.write('b = "' + b + '"<br>') if (typeof c != 'undefined') document.write('c = "' + c + '"<br>') function test() { a = 123 var b = 456 if (a == 123) var c = 789 } </script>

La salida de este script es la siguiente línea:

a = "123"

Esto muestra que solo la variable a recibió un alcance global, que es exactamente lo que esperaríamos, ya que las variables b y c recibieron un alcance local al estar precedidas por la palabra clave var.

Si tu navegador emite una advertencia sobre que b está indefinido, la advertencia es correcta pero se puede ignorar.

Utilizando let y const

JavaScript ahora ofrece dos nuevas palabras clave: let y const. La palabra clave let es prácticamente un reemplazo para var, pero tiene la ventaja de que no puedes redeclarar una variable una vez que lo hayas hecho con let, aunque sí puedes con var.

Verás, el hecho de que pudieras redeclarar variables utilizando var estaba llevando a errores oscuros, como el siguiente:

1
2
3
4
5
6
7
8
9
var hello = "Hello there" var counter = 1 if (counter > 0) { var hello = "How are you?" } document.write(hello)

¿Puedes ver el problema? Debido a que counter es mayor que 0 (ya que lo inicializamos en 1), el string hello se redefine como "How are you?" (¿Cómo estás?) y luego se muestra en el documento.

Ahora, si reemplazas var con let (como lo siguiente), la segunda declaración será ignorada, y se mostrará el string original "Hello there":

1
2
3
4
5
6
7
8
9
let hello = "Hello there" let counter = 1 if (counter > 0) { let hello = "How are you?" } document.write(hello)

La palabra clave var tiene un alcance global (si está fuera de cualquier bloque o función) o de función, y las variables declaradas se inicializan con undefined, pero la palabra clave let tiene un alcance global o de bloque, y las variables no se inicializan.

Cualquier variable asignada utilizando let tiene un alcance dentro de todo el documento si se declara fuera de cualquier bloque, o, si se declara dentro de un bloque delimitado por {} (lo que incluye funciones), su alcance se limita a ese bloque (y cualquier sub-bloque anidado). Si declaras una variable dentro de un bloque pero intentas acceder a ella desde fuera de ese bloque, se devolverá un error, como en el siguiente caso, que fallará en el document.write porque hello no tendrá valor:

1
2
3
4
5
6
7
8
let counter = 1 if (counter > 0) { let hello = "How are you?" } document.write(hello)

Puedes usar let para declarar variables con el mismo nombre que las variables previamente declaradas, siempre y cuando sean dentro de un nuevo ámbito, en cuyo caso cualquier valor anterior asignado a una variable con el mismo nombre en el ámbito anterior se volverá inaccesible para el nuevo ámbito, porque la nueva variable con el mismo nombre se maneja totalmente diferente de la anterior. Solo tiene alcance dentro del bloque actual, o de cualquier sub-bloque (a menos que se use otro let para declarar otra variable con el mismo nombre en un sub-bloque).

Es una buena práctica intentar evitar la reutilización de nombres significativos de variables, o corres el riesgo de causar confusión. Sin embargo, las variables de bucle o índice como i (u otros nombres cortos y simples) generalmente pueden reutilizarse en nuevos ámbitos sin causar confusión.

Puedes aumentar aún más tu control sobre el alcance declarando una variable con un valor constante, es decir, uno que no pueda ser cambiado. Esto es beneficioso cuando has creado una variable que lo estás tratando como una constante pero la has declarado utilizando solo var o let, porque podrías tener ocasiones que en tu código intentes cambiar ese valor, lo cual estaría permitido pero sería un error.

Sin embargo, si utilizas la palabra clave const para declarar la variable y asignar su valor, cualquier intento de cambiar más tarde su valor será prohibido, y tu código se detendrá con un mensaje de error en la consola similar a:

Uncaught TypeError: Assignment to constant variable

El siguiente código causará exactamente ese error:

1
2
3
4
5
6
7
8
9
const hello = "Hello there" let counter = 1 if (counter > 0) { hello = "How are you?" } document.write(hello)

Al igual que let, las declaraciones const también tienen un alcance de bloque (dentro de secciones {} y cualquier sub-bloque), lo que significa que puedes tener variables constantes con el mismo nombre pero con diferentes valores en diferentes ámbitos de un fragmento de código. Sin embargo, te recomiendo encarecidamente que intentes evitar la duplicación de nombres y mantengas cualquier nombre de constante para un solo valor a lo largo de cada programa, utilizando un nuevo nombre de constante donde necesites una nueva constante.

En resumen: var tiene un alcance global o de función, y let y const tienen un alcance global o de bloque. Tanto var como let pueden ser declarados sin ser inicializados, mientras que const debe ser inicializado durante la declaración. La palabra clave var se puede reutilizar para redeclarar una variable var, pero let y const no pueden. Finalmente, const no puede ser redeclarado ni reasignado.

Nota

Es posible que prefieras utilizar una consola de desarrollador para pruebas como estas (y en otras partes de este libro) como se explicó anteriormente en "Depuración de errores en JavaScript", en cuyo caso puedes reemplazar document.write con console.log, y la salida se mostrará en la consola en lugar del documento del navegador. También es una mejor opción para que JavaScript se ejecute una vez que el documento se haya cargado completamente, porque en ese momento document.write reemplazaría el documento actual, en lugar de agregarle contenido, lo cual probablemente no sea lo que esperes.

El Document Object Model

El diseño de JavaScript es muy inteligente. En lugar de simplemente crear otro lenguaje de scripting (lo que hubiera sido una mejora bastante buena en ese momento), había una visión de construirlo alrededor del ya existente Document Object Model de HTML. Este modelo descompone las partes de un documento HTML en objetos discretos, cada uno con sus respectivas propiedades y métodos, y cada uno sujeto al control de JavaScript.

JavaScript separa objetos, propiedades y métodos utilizando un punto (una buena razón por la cual + es el operador de concatenación de strings en JavaScript, en lugar del punto). Por ejemplo, consideremos una tarjeta de presentación como un objeto al que llamaremos card. Este objeto contiene propiedades como su nombre, dirección, número de teléfono, y así sucesivamente. En la sintaxis de JavaScript, estas propiedades se verían así:

card.name
card.phone
card.address

Sus métodos son funciones que recuperan, modifican y actúan de otras maneras sobre las propiedades. Por ejemplo, para invocar un método que muestre las propiedades del objeto card, podrías utilizar una sintaxis como esta:

1
card.display()

Echa un vistazo a algunos de los ejemplos anteriores en este capítulo y observa dónde se utiliza la instrucción document.write. Ahora que entiendes cómo JavaScript se basa en objetos, verás que write es en realidad un método del objeto document.

Dentro de JavaScript, existe una jerarquía de objetos padre e hijo, que es lo que se conoce como el Document Object Model. (DOM; ver Figura 14-3).

figura_14-3.png
Figura 14-3. Ejemplo de jerarquía de objetos del DOM

La figura utiliza etiquetas HTML con las que ya estás familiarizado para ilustrar la relación padre/hijo entre los distintos objetos de un documento. Por ejemplo, una URL dentro de un enlace es parte del cuerpo de un documento HTML. En JavaScript, se hace referencia a ello así:

1
url = document.links.linkname.href

Observa cómo esto sigue la columna central hacia abajo. La primera parte, document, se refiere a las etiquetas <html> y <body>; links.linkname se refiere a la etiqueta <a>, y href al atributo href.

Vamos a convertir la expresión en HTML y un script para leer las propiedades de un enlace. Escribe el Ejemplo 14-7 y guárdalo como linktest.html; luego ábrelo en tu navegador.

Ejemplo 14-7. Leer una URL de un enlace con JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
<html> <head> <title>Link Test</title> </head> <body> <a id="mylink" href="http://mysite.com">Click me</a><br> <script> url = document.links.mylink.href document.write('The URL is ' + url) </script> </body> </html>

Observa la forma corta de las etiquetas <script>, donde he omitido el parámetro type="text/JavaScript" para ahorrarte un poco de escritura. Si lo deseas, solo con el fin de probar esto (y otros ejemplos), también podrías omitir todo lo que esté fuera de las etiquetas <script> y </script>. El resultado de este ejemplo es el siguiente:

Click me
The URL is http://mysite.com

La segunda línea de la salida proviene del método document.write. Observa cómo el código sigue el árbol del documento desde document hasta links, luego a mylink (el id dado al enlace) y finalmente a href (el valor de destino de la URL).

También hay una forma corta que funciona igual de bien, que comienza con el valor en el atributo id: mylink.href. Entonces, puedes reemplazar esto:

1
url = document.links.mylink.href

con lo siguiente:

1
url = mylink.href

Otro uso del símbolo $

Como se mencionó anteriormente, el símbolo $ está permitido en los nombres de variables y funciones de JavaScript. Debido a esto, a veces puedes encontrarte con código de aspecto extraño como este:

1
url = $('mylink').href

Algunos programadores con iniciativa han decidido que la función getElementById es tan importante en JavaScript que han escrito una función para reemplazar la llamada $, como en jQuery (aunque jQuery usa el $ para mucho más que eso ver Capítulo 22), como se muestra en el Ejemplo 14-8.

Ejemplo 14-8. Una función que reemplaza el método getElementById

1
2
3
4
5
6
<script> function $(id) { return document.getElementById(id) } </script>

Por lo tanto, siempre y cuando hayas incluido la función $ en tu código, una sintaxis como esta:

1
$('mylink').href

puede reemplazar al siguiente código:

1
document.getElementById('mylink').href

Utilizando el DOM

El objeto links es en realidad un array de URLs, por lo que la URL mylink en el Ejemplo 14-7 también puede referirse de manera segura en todos los navegadores de la siguiente manera (porque es el primer y único enlace):

1
url = document.links[0].href

Si quieres saber cuántos enlaces hay en un documento completo, puedes consultar la propiedad length del objeto links así:

1
numlinks = document.links.length

Puedes extraer y mostrar todos los enlaces en un documento de esta manera:

1
2
for (j = 0; j < document.links.length; ++j) document.write(document.links[j].href + '<br>')

El length de algo es una propiedad de cada array, y de muchos objetos también. Por ejemplo, el número de elementos en el historial web de tu navegador se puede consultar así:

1
document.write(history.length)

Para evitar que los sitios web espíen tu historial de navegación, el objeto history almacena solo el número de sitios en el array: no puedes leer ni escribir en estos valores. Pero puedes reemplazar la página actual con una del historial, si sabes en qué posición se encuentra dentro del historial. Esto puede ser muy útil en casos en los que sabes que ciertas páginas en el historial provienen de tu sitio, o simplemente desees que el navegador retroceda una o más páginas, lo cual puedes hacer con el método go del objeto history. Por ejemplo, para hacer que el navegador retroceda tres páginas, emita el siguiente comando:

1
history.go(-3)

También puedes utilizar los siguientes métodos para avanzar o retroceder una página a la vez:

1
2
history.back() history.forward()

De manera similar, puedes reemplazar la URL actualmente cargada con una de tu elección, así:

1
document.location.href = 'http://google.com'

Por supuesto, hay mucho más cosas en el DOM que leer y modificar enlaces. A medida que avances a través de los siguientes capítulos sobre JavaScript, te familiarizarás bastante con el DOM y en la manera de cómo acceder a él.

Sobre document.write

Al enseñar programación, es necesario tener una forma rápida y fácil de mostrar los resultados de las expresiones. En PHP (por ejemplo) existen las declaraciones echo y print, que simplemente envían texto al navegador, así que es fácil. En JavaScript, sin embargo, existen las siguientes alternativas.

Utilizando console.log

La función console.log mostrará en la consola del navegador actual el resultado de cualquier valor o expresión que se le pase. Se trata de un modo especial de presentación, con un marco o ventana separada de la ventana del navegador, en la cual se pueden mostrar errores y otros mensajes. Aunque es genial para programadores experimentados, no es la mejor opción para principiantes porque la salida no se parece al contenido web en el navegador.

Utilizando alert

La función alert muestra en una ventana emergente valores o expresiones que se le pasan, la cual requiere que hagas clic en un botón para cerrarla. Claramente, esto puede volverse bastante irritante muy rápidamente, y tiene la desventaja de mostrar solo el mensaje actual, borrando los anteriores.

Escritura en elementos

Es posible escribir directamente en el texto de un elemento HTML, lo cual es una solución bastante elegante (y la mejor para sitios web en producción), excepto que para este libro cada ejemplo requeriría que se creara dicho elemento y algunas líneas de código JavaScript para acceder a él. Esto interfiere con la enseñanza principal de un ejemplo y haría que el código pareciera excesivamente engorroso y confuso.

Utilizando document.write

La función document.write escribe un valor o expresión en la ubicación actual del navegador y, por lo tanto, es la opción perfecta para mostrar resultados rápidamente. Mantiene todos los ejemplos breves y concisos, colocando la salida justo allí en el navegador junto al contenido web y el código.

Sin embargo, es posible que hayas escuchado que esta función es considerada insegura por algunos desarrolladores, porque cuando la llamas después de que una página web se ha cargado completamente, sobrescribirá el documento actual. Aunque esto es correcto, no se aplica a ninguno de los ejemplos de este libro, porque todos ellos utilizan document.write de la manera en que originalmente se pretendía: como parte del proceso de creación de la página, llamándolo solo antes de que la página haya terminado de cargarse y mostrarse.

No obstante, aunque uso document.write de esta manera para ejemplos simples, nunca lo utilizo en código de producción (excepto en las circunstancias más raras en las que realmente es necesario). En su lugar, casi siempre utilizo la opción anterior de escribir directamente en un elemento especialmente preparado, como en los ejemplos más complejos a partir del Capítulo 18. (que acceden a la propiedad innerHTML de los elementos para presentar la salida del programa).

Así que, por favor, recuerda que cuando veas que se llama a document.write en este libro, está ahí solo para simplificar un ejemplo, y les recomiendo que también usen la función de la misma manera para obtener resultados rápidos de prueba.

Con la advertencia explicada, en el siguiente capítulo continuaremos nuestra exploración con JavaScript analizando cómo controlar el flujo del programa y escribir expresiones.

Preguntas

  1. ¿Qué etiquetas utilizas para incluir código JavaScript?
  2. Por defecto, ¿a qué parte de un documento se enviará la salida del código JavaScript?
  3. ¿Cómo puedes incluir código JavaScript desde otra fuente en tus documentos?
  4. ¿Qué función de JavaScript es equivalente a echo o print de PHP?
  5. ¿Cómo puedes crear un comentario en JavaScript?
  6. ¿Cuál es el operador de concatenación de strings en JavaScript?
  7. ¿Qué palabra clave puedes utilizar dentro de una función en JavaScript para definir una variable que tenga un alcance local?
  8. Proporciona dos métodos compatibles con múltiples navegadores para mostrar la URL asignada al enlace con un id de thislink.
  9. ¿Qué dos comandos de JavaScript harán que el navegador cargue la página anterior en su array de historial?
  10. ¿Qué comando de JavaScript usarías para reemplazar el documento actual con la página principal del sitio web oreilly.com?

Ver "Respuestas del capítulo 14" del Apéndice A para comprobar las respuestas a estas preguntas.



Expresiones y control de flujo en JavaScript

En el capítulo anterior, introduje los conceptos básicos de JavaScript y el DOM. Ahora es el momento de ver cómo construir expresiones complejas en JavaScript y cómo controlar el flujo del programa de tus scripts utilizando declaraciones condicionales.

Expresiones

Las expresiones de JavaScript son muy similares a las de PHP. Como aprendiste en el Capítulo 4, una expresión es una combinación de valores, variables, operadores y funciones que da como resultado un valor; el resultado puede ser un número, un string o un valor booleano (que se evalúa como true o false).

El ejemplo 15-1 muestra algunas expresiones simples. En cada línea, imprime una letra entre a y d, seguida de dos puntos y el resultado de las expresiones. La etiqueta <br> está ahí para crear un salto de línea y separar la salida en cuatro líneas (recuerda que tanto <br> como <br/> son aceptables en HTML5, así que decidí utilizar el primer estilo por brevedad).

Ejemplo 15-1. Cuatro simples expresiones booleanas

1
2
3
4
5
6
<script> document.write("a: " + (42 > 3) + "<br>") document.write("b: " + (91 < 4) + "<br>") document.write("c: " + (8 == 2) + "<br>") document.write("d: " + (4 < 17) + "<br>") </script>

La salida de este código es la siguiente:

a: true
b: false
c: false
d: true

Nota que ambas expresiones a: y d: se evalúan como true, pero b: y c: se evalúan como false. A diferencia de PHP (que imprimiría el número 1 y nada, respectivamente), se muestran los strings true y false.

En JavaScript, cuando estás comprobando si un valor es true o false, todos los valores se evalúan como true excepto los siguientes, que se evalúan como false: el string false en sí misma, 0, -0, la cadena vacía, null, undefined y NaN (Not a Number, un concepto de ingeniería informática para el resultado de una operación ilegal de punto flotante como la división entre cero).

Como puedes ver, me estoy refiriendo a true y false en minúsculas. Esto se debe a que, a diferencia de PHP, estos valores deben estar en minúsculas en JavaScript. Por lo tanto, solo se mostrará la primera de las dos siguientes sentencias, imprimiendo la palabra en minúsculas true, porque la segunda causará un error de 'TRUE' no está definido:

1
2
if (1 == true) document.write('true') // True if (1 == TRUE) document.write('TRUE') // Will cause an error

Nota

Recuerda que cualquier fragmento de código que desees escribir y probar por ti mismo en un archivo HTML, debe estar encerrado dentro de las etiquetas <script> y </script>.

Literales y variables

La forma más simple de una expresión es una literal, que significa algo que se evalúa a sí mismo, como el número 22 o el string Presiona Enter. Una expresión también podría ser una variable, que evalúa el valor que se le ha asignado. Ambos son tipos de expresiones, porque devuelven un valor.

El Ejemplo 15-2 muestra tres literales diferentes y dos variables, todas ellas devuelven valores, aunque de diferentes tipos.

Ejemplo 15-2. Cinco tipos de literales

1
2
3
4
5
6
7
8
9
<script> myname = "Peter" myage = 24 document.write("a: " + 42 + "<br>") // Numeric literal document.write("b: " + "Hi" + "<br>") // String literal document.write("c: " + true + "<br>") // Boolean literal document.write("d: " + myname + "<br>") // String variable document.write("e: " + myage + "<br>") // Numeric variable </script>

Y, como es de esperar, puedes ver el valor de retorno de todo esto en la siguiente salida:

a: 42
b: Hi
c: true
d: Peter
e: 24

Los operadores te permiten crear expresiones más complejas que se evalúan en resultados útiles. Cuando combinas asignaciones o estructuras de control de flujo con expresiones, el resultado es una sentencia.

El ejemplo 15-3 muestra uno de cada uno. El primero asigna el resultado de la expresión 366 - day_number a la variable days_to_new_year, y el segundo muestra un mensaje amigable solo si la expresión days_to_new_year < 30 se evalúa como true.

Ejemplo 15-3. Dos sentencias simples de JavaScript

1
2
3
4
5
6
<script> day_number = 127 // For example days_to_new_year = 366 - day_number if (days_to_new_year < 30) document.write("It's nearly New Year") else document.write("It's a long time to go") </script>

Operadores

JavaScript ofrece muchos operadores potentes, que van desde operadores aritméticos, de string y lógicos hasta de asignación, comparación, etc. (ver la Tabla 15-1).

Tabla 15-1. Tipos de operadores de JavaScript

Operador Descripción Ejemplo
Aritmético Matemáticas básicas a + b
Array Manipulación de arrays a + b
Asignación Asignar valores a = b + 23
Operador a nivel de bit Manipula bits en bytes 12 ^ 9
Comparación Comparar dos valores a < b
Incremento/decremento Sumar o restar en uno a++
Lógico Booleano a && b
String Concatenación a + 'string'

Cada operador admite un número diferente de operandos:

  • Los operadores unarios, como el incremento (a++) o la negación (-a), admiten un solo operando.
  • Los operadores binarios, que representan la mayoría de los operadores de JavaScript (incluyendo la suma, la resta, la multiplicación y la división) admiten dos operandos.
  • El único operador ternario, que adopta la forma ? x : y, requiere tres operandos. Es una declaración if concisa de una sola línea que elige entre dos expresiones en función de una tercera.

Precedencia de operadores

Al igual que PHP, JavaScript utiliza la precedencia de operadores, en la que algunos operadores de una expresión se procesan antes que otros y, por lo tanto, se evalúan primero. La Tabla 15-2 enumera los operadores de JavaScript y sus precedencias.

Tabla 15-2. Precedencia de los operadores de JavaScript (de mayor a menor)

Operador(es) Tipo(s)
() [] . Paréntesis, llamada, y miembro
++ -- Incremento/decremento
+ - ~ ! Unario, operador a nivel de bit y lógico
* / % Aritmético
+ - Aritmético y string
<< >> >>> Operador a nivel de bit
< > <= >= Comparación
== != === !== Comparación
& ^ | Operador a nivel de bit
&& Lógico
|| Lógico
?: Ternario
= += -= *= /= %= Asignación
<<= >>= >>>= &= ^= |= Asignación
, Separador

Asociatividad

La mayoría de los operadores en JavaScript se procesan de izquierda a derecha en una ecuación. Pero algunos operadores en su lugar requieren un procesamiento de derecha a izquierda. La dirección del procesamiento se denomina asociatividad del operador.

Esta asociatividad se vuelve importante cuando no fuerzas explícitamente la precedencia (lo cual deberías hacer siempre, por cierto, porque hace que el código sea más legible y menos propenso a errores). Por ejemplo, observe los siguientes operadores de asignación, mediante los cuales se establecen tres variables con en el valor 0:

1
level = score = time = 0

Esta asignación múltiple solo es posible porque la parte más a la derecha de la expresión se evalúa primero y luego el procesamiento continúa de derecha a izquierda. La Tabla 15-3 enumera los operadores de JavaScript y su asociatividad.

Tabla 15-3. Operadores y asociatividad

Operador Descripción Asociatividad
++ -- Incremento y decremento Ninguna
new Crea un nuevo objecto Derecha
+ - ~ ! Unario y operador a nivel de bit Derecha
?: Ternario Derecha
= *= /= %= += -= Asignación Derecha
<<= >>= >>>= &= ^= |= Asignación Derecha
, Separador Izquierda
+ - * / % Aritmético Izquierda
<< >> >>> Operador a nivel de bit Izquierda
< <= > >= == != === != Aritmético Izquierda

Operadores relacionales

Los operadores relacionales comprueban dos operandos y devuelven un resultado booleano de true o false. Existen tres tipos de operadores relacionales: de igualdad, comparación y lógico.

Operadores de igualdad

El operador de igualdad es == (que no debe confundirse con el operador de asignación =). En el Ejemplo 15-4, la primera instrucción asigna un valor, y la segunda comprueba si son iguales. Tal como está, no se imprimirá nada, porque a month se le asigna el valor del string July, y por lo tanto la comprobación de que tenga el valor de October fallará.

Ejemplo 15-4. Asignación de un valor y prueba de igualdad

1
2
3
4
<script> month = "July" if (month == "October") document.write("It's the Fall") </script>

Si los dos operandos de una expresión de igualdad son de diferentes tipos, JavaScript los convertirá al tipo dato más adecuado. Por ejemplo, cualquier string compuesto completamente por números será convertido a números cada vez que se compare con un número. En el Ejemplo 15-5, a y b son dos valores diferentes (uno es un número y el otro es un string), y por lo tanto, normalmente esperaríamos que ninguna de las sentencias if produzca un resultado.

Ejemplo 15-5. Los operadores de igualdad e identidad

1
2
3
4
5
6
<script> a = 3.1415927 b = "3.1415927" if (a == b) document.write("1") if (a === b) document.write("2") </script>

Sin embargo, si ejecutas el ejemplo, verás que imprime el número 1, lo que significa que la primera sentencia if se evaluó como true. Esto se debe a que el valor del string de b se convirtió temporalmente a un número, y por lo tanto ambas mitades de la ecuación tenían un valor numérico de 3.1415927.

En contraste, la segunda sentencia if utiliza el operador de identidad, tres signos de igual uno a lado del otro, lo que evita que JavaScript convierta automáticamente los tipos. Por lo tanto, a y b son diferentes, por lo que no se muestra ningún resultado.

Al igual que al forzar la precedencia de los operadores, siempre que tengas dudas sobre cómo JavaScript convertirá los tipos de datos de los operandos, puedes utilizar el operador de identidad para desactivar este comportamiento.

Operadores de comparación

Utilizando operadores de comparación, puedes probar más que solo igualdad y desigualdad. JavaScript también te ofrece > (es mayor que), < (es menor que), >= (es mayor o igual que) y <= (es menor o igual que) con los que puedes jugar. El Ejemplo 15-6 muestra como puedes utilizar estos operadores.

Ejemplo 15-6. Los cuatro operadores de comparación

1
2
3
4
5
6
7
<script> a = 7; b = 11 if (a > b) document.write("a is greater than b<br>") if (a < b) document.write("a is less than b<br>") if (a >= b) document.write("a is greater than or equal to b<br>") if (a <= b) document.write("a is less than or equal to b<br>") </script>

En este ejemplo, donde a es 7 y b es 11, se produce la siguiente salida (porque 7 es menor que 11 y también menor o igual a 11):

a is less than b
a is less than or equal to b

Operadores lógicos

Los operadores lógicos producen resultados verdaderos o falsos y también se conocen como operadores booleanos. Hay tres de ellos en JavaScript (ver la Tabla 15-4).

Tabla 15-4. Operadores lógicos de JavaScript

Operador lógico Descripción
&& (and) true si ambos operandos son true
|| (or) true si cualquiera de los dos operandos es true
! (not) true si el operando es false, o false si el operando es true

Puedes ver cómo se pueden utilizar en el Ejemplo 15-7, que produce 0, 1 y true.

Ejemplo 15-7. Los operadores lógicos en uso

1
2
3
4
5
6
<script> a = 1; b = 0 document.write((a && b) + "<br>") document.write((a || b) + "<br>") document.write(( !b ) + "<br>") </script>

La sentencia && requiere que ambos operandos sean true para devolver un valor true, la sentencia || será true si cualquiera de los valores es true, y la tercera sentencia realiza un NOT en el valor de b, convirtiéndolo de 0 a un valor true.

El operador || puede causar problemas involuntarios, porque el segundo operando no se evaluará si el primero se evalúa como true. En el Ejemplo 15-8, la función getnext nunca se llamará si finished tiene un valor de 1 (estos son puramente ejemplos, y la acción de getnext es irrelevante para esta explicación, solo piénselo como una función que hace algo cuando se llama).

Ejemplo 15-8. Una sentencia utilizando el operador ||

1
2
3
<script> if (finished == 1 || getnext() == 1) done = 1 </script>

Si necesitas que getnext se llame en cada sentencia if, debes reescribir el código como se muestra en el Ejemplo 15-9.

Ejemplo 15-9. La sentencia if...or modificada para asegurar la llamada a getnext

1
2
3
4
<script> gn = getnext() if (finished == 1 || gn == 1) done = 1; </script>

En este caso, el código en la función getnext se ejecutará y su valor de retorno se almacenará en gn antes de la sentencia if.

La Tabla 15-5 muestra todas las posibles variaciones del uso de los operadores lógicos. También debes tener en cuenta que !true es igual a false y !false es igual a true.

Tabla 15-5. Todas las posibles expresiones lógicas

Entrada Operadores y resultados
a b && ||
true true true true
true false false true
false true false true
false false false false

Declaración with

La declaración with no la has visto en los capítulos anteriores sobre PHP, porque es exclusiva de JavaScript, y también es una que, aunque necesitas conocerla, no deberías utilizarla. Con él (si me entiendes), puedes simplificar algunos tipos de declaraciones de JavaScript reduciendo muchas referencias a un objeto a una solo referencia. Se asume que las referencias a las propiedades y métodos dentro del bloque with se aplican a ese objeto.

Por ejemplo, considerando el código del Ejemplo 15-10, en el cual la función document.write nunca hace referencia a la variable string por su nombre.

Ejemplo 15-10. Utilizando la declaración with

1
2
3
4
5
6
7
8
9
<script> string = "The quick brown fox jumps over the lazy dog" with (string) { document.write("The string is " + length + " characters<br>") document.write("In upper case it's: " + toUpperCase()) } </script>

Aunque string nunca es referenciada directamente mediante document.write, este código consigue mostrar lo siguiente:

The string is 43 characters
In upper case it's: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG

Así es como funciona el código: el intérprete de JavaScript reconoce que la propiedad length y el método toUpperCase deben aplicarse en algún objeto. Como son independientes, el intérprete asume que se aplican al objeto string especificado en la declaración with.

Nota

Utilizar with ya no se recomienda y ahora está prohibido en el modo estricto de ECMAScript 5. La alternativa recomendada es asignar a una variable temporal el objeto cuyas propiedades deseas acceder. Asegúrate de tener esto en cuenta para poder actualizarlo (si es necesario) cuando lo veas en el código de otras personas, pero no lo uses tú mismo.

Utilizando onerror

Utilizando el evento onerror o una combinación de las palabras reservadas try y catch, puedes capturar errores de JavaScript y manejarlos tú mismo.

Los eventos son acciones que puede detectar JavaScript. Cada elemento de una página web tiene ciertos eventos que pueden activar funciones de JavaScript. Por ejemplo, el evento onclick de un elemento button se puede configurar para llamar a una función y hacer que se ejecute cada vez que un usuario haga clic en el botón.

Ejemplo 15-11. Un script que emplea el evento onerror

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script> onerror = errorHandler document.writ("Welcome to this website") // Deliberate error function errorHandler(message, url, line) { out = "Sorry, an error was encountered.\n\n"; out += "Error: " + message + "\n"; out += "URL: " + url + "\n"; out += "Line: " + line + "\n\n"; out += "Click OK to continue.\n\n"; alert(out); return true; } </script>

La primera línea de este script indica al evento de error que use la nueva función errorHandler a partir de ahora. Esta función toma tres parámetros: un mensaje (message), una URL (url) y un número de línea (line), por lo que es sencillo mostrar todo esto en una ventana emergente de alerta.

Luego, para probar la nueva función, colocamos intencionalmente un error de sintaxis en el código con una llamada a document.writ en lugar de document.write (falta la e al final). La Figura 15-1 muestra el resultado de ejecutar este script en un navegador. Usar onerror de esta manera también puede ser bastante útil durante el proceso de depuración.

figura_15-1.png
Figura 15-1. Uso del evento onerror con un pop-up del método alert

Utilizando try...catch

Las palabras clave try y catch son más estándar y más flexibles que la técnica onerror mostrada en la sección anterior. Estas palabras clave te permiten detectar errores en una sección de código determinado, en lugar de hacerlo para todos los scripts de un documento. Sin embargo, no detectan errores de sintaxis, para los cuales necesitas onerror.

El constructor try...catch es compatible con todos los navegadores principales y es útil cuando quieres detectar una cierta condición que sabes que podría ocurrir en una parte específica de tu código.

Por ejemplo, en el Capítulo 18 exploraremos las técnicas de Ajax que utilizan el objeto XMLHttpRequest. Por lo tanto, podemos utilizar try y catch para detectar este caso y hacer algo más si la función no está disponible. El ejemplo 15-12 muestra cómo hacerlo.

Ejemplo 15-12. Detección de un error con try y catch

1
2
3
4
5
6
7
8
9
10
<script> try { request = new XMLHttpRequest() } catch (err) { // Use a different method to create an XMLHttpRequest object } </script>

También hay otra palabra reservada asociada con try y catch llamada finally que siempre se ejecuta, independientemente de si ocurre un error en la cláusula try. Para usarlo, simplemente añade algo como las siguientes declaraciones después de una declaración catch:

1
2
3
4
finally { alert("The 'try' clause was encountered") }

Condicionales

Las condicionales alteran el flujo del programa. Te permiten hacer preguntas sobre determinadas cosas y responder a las respuestas que obtienes de diferentes maneras. Hay tres tipos de condicionales no iterativos: la declaración if, la declaración switch y el operador ?.

Declaración if

Varios ejemplos en este capítulo ya han utilizado declaraciones if. El código dentro de tal declaración se ejecuta solo si la expresión dada se evalúa como true. Las sentencias if multilínea requieren llaves alrededor de ellas, pero al igual que en PHP, puedes omitir las llaves para una sola sentencia, aunque a menudo es una buena idea usarlas de todos modos, especialmente cuando escribes código en el que el número de acciones dentro de una declaración if podría cambiar a medida que avanza el desarrollo. Por lo tanto, las siguientes sentencias son válidas:

1
2
3
4
5
6
7
if (a > 100) { b = 2 document.write("a is greater than 100") } if (b == 10) document.write("b is equal to 10")

Declaración else

Cuando no se ha cumplido una condición, puedes ejecutar una alternativa utilizando una declaración else, así:

1
2
3
4
5
6
7
8
if (a > 100) { document.write("a is greater than 100") } else { document.write("a is less than or equal to 100") }

A diferencia de PHP, JavaScript no tiene una declaración elseif, pero eso no es un problema porque puedes utilizar un else seguido de otro if para formar el equivalente de una declaración elseif, así:

1
2
3
4
5
6
7
8
9
10
11
12
if (a > 100) { document.write("a is greater than 100") } else if (a < 100) { document.write("a is less than 100") } else { document.write("a is equal to 100") }

Como puedes ver, es posible utilizar otro else después del nuevo if, al que podría seguir igualmente otra declaración if, y así sucesivamente. Aunque he mostrado llaves en las declaraciones, dado que cada una es una sola línea, el ejemplo anterior podría escribirse de la siguiente manera:

1
2
3
if (a > 100) document.write("a is greater than 100") else if (a < 100) document.write("a is less than 100") else document.write("a is equal to 100")

Declaración switch

La declaración switch es útil cuando una variable o el resultado de una expresión puede tener múltiples valores y quieres realizar una función diferente para cada valor.

Por ejemplo, el siguiente código emplea el sistema de menú en PHP que construimos en el Capítulo 4 y lo convierte a JavaScript. Funciona pasando un único string al código del menú principal de acuerdo con lo que el usuario solicite. Digamos que las opciones son Inicio (Home), Acerca de (About), Noticias (News), Iniciar sesión (Login) y Enlaces (Links), y establecemos la variable page (página) en una de ellas en función de la entrada del usuario.

El código escrito para esto utilizando if...else if... podría verse como en el Ejemplo 15-13.

Ejemplo 15-13. Una declaración if...else if... de varias líneas

1
2
3
4
5
6
7
<script> if (page == "Home") document.write("You selected Home") else if (page == "About") document.write("You selected About") else if (page == "News") document.write("You selected News") else if (page == "Login") document.write("You selected Login") else if (page == "Links") document.write("You selected Links") </script>

Pero usando una estructura switch, el código podría verse como en el Ejemplo 15-14.

Ejemplo 15-14. Una estructura switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script> switch (page) { case "Home": document.write("You selected Home") break case "About": document.write("You selected About") break case "News": document.write("You selected News") break case "Login": document.write("You selected Login") break case "Links": document.write("You selected Links") break } </script>

La variable page se menciona solo una vez al inicio de la declaración switch. Después, el comando case comprueba las coincidencias. Cuando ocurre una coincidencia, se ejecuta la declaración condicional correspondiente. Por supuesto, un programa real tendría código aquí para mostrar o saltar a una página, en lugar de simplemente decirle al usuario lo que ha seleccionado.

Nota

También puedes proporcionar múltiples casos para una sola acción. Por ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
switch (heroName) { case "Superman": case "Batman": case "Wonder Woman": document.write("Justice League") break case "Iron Man": case "Captain America": case "Spiderman": document.write("The Avengers") break }

Ruptura

Como puedes ver en el Ejemplo 15-14, al igual que con PHP, el comando break permite que tu código salga de la declaración switch una vez que se ha cumplido una condición. Recuerda incluir el break a menos que quieras seguir ejecutando las sentencias del siguiente case.

Acción por defecto

Cuando no se cumple ninguna condición, puedes especificar una acción por defecto para una declaración switch utilizando la palabra reserveda default. El Ejemplo 15-15 muestra un fragmento de código que podría insertarse en el Ejemplo 15-14.

Ejemplo 15-15. Una declaración por defecto para agregar al Ejemplo 15-14

1
2
3
default: document.write("Unrecognized selection") break

El operador ?

El operador ternario (?), combinado con el caracter :, proporciona una forma rápida de realizar pruebas if...else. Con él puedes escribir una expresión para evaluar y luego acompañarla con el símbolo ? y el código a ejecutar si la expresión es true. Después de eso, colocas un : y el código a ejecutar si la expresión se evalúa como false.

El ejemplo 15-16 muestra el uso del operador ternario para imprimir si la variable a es menor o igual a 5 e imprime algo de cualquier manera.

Ejemplo 15-16. Utilizando el operador ternario

1
2
3
4
5
6
7
<script> document.write( a <= 5 ? "a is less than or equal to 5" : "a is greater than 5" ) </script>

La declaración ha sido dividida en varias líneas para mayor claridad, pero es más probable que utilizes una declaración en una sola línea, de esta manera:

1
size = a <= 5 ? "short" : "long"

Bucles

Nuevamente, encontrarás muchas similitudes cercanas entre JavaScript y PHP en lo que respecta a los bucles. Ambos lenguajes admiten bucles while, do...while y for.

Bucles while

Un bucle while en JavaScript comprueba primero el valor de una expresión y comienza a ejecutar las instrucciones dentro del bucle solo si esa expresión es true. Si es false, la ejecución salta a la siguiente instrucción de JavaScript (si la hay).

Al completar una iteración del bucle, la expresión se vuelve a evaluar para ver si es true, y el proceso continúa hasta que la expresión se evalúe a false o hasta que la ejecución se detenga de otra manera. El ejemplo 15-17 muestra este bucle.

Ejemplo 15-17. Un bucle while

1
2
3
4
5
6
7
8
9
<script> counter = 0 while (counter < 5) { document.write("Counter: " + counter + "<br>") ++counter } </script>

Este script produce lo siguiente:

Counter: 0
Counter: 1
Counter: 2
Counter: 3
Counter: 4

Precaución

Si la variable counter (contador) no se incrementara dentro del bucle, es bastante posible que algunos navegadores no ofrezcan ninguna respuesta debido a un bucle interminable, y la página no sea fácil de cerrar ni siquiera con Escape o con el botón de Detener. Así que, ten cuidado con tus bucles de JavaScript.

Bucles do...while

Cuando necesites que un bucle itere al menos una vez antes de realizar cualquier prueba, utiliza un bucle do...while, que es similar a un bucle while, excepto que la expresión de prueba se verifica solo después de cada iteración del bucle. Entonces, para mostrar los primeros siete resultados de la tabla del 7, podrías usar un código como el del Ejemplo 15-18.

Ejemplo 15-18. Un bucle do...while

1
2
3
4
5
6
7
8
<script> count = 1 do { document.write(count + " times 7 is " + count * 7 + "<br>") } while (++count <= 7) </script>

Como era de esperar, este bucle produce lo siguiente:

1 times 7 is 7
2 times 7 is 14
3 times 7 is 21
4 times 7 is 28
5 times 7 is 35
6 times 7 is 42
7 times 7 is 49

Bucles for

Un bucle for combina lo mejor de todos los mundos en una única estructura de bucle que te permite pasar tres parámetros en cada declaración:

  • Una expresión de inicialización
  • Una expresión de condición
  • Una expresión de modificación

Estos están separados por punto y coma, así: for (expr1; expr2; expr3). La expresión de inicialización se ejecuta al inicio de la primera iteración del bucle. En el caso del código para la tabla de multiplicar del 7, count se inicializaría con el valor 1. Luego, cada vez que se recorre el bucle, se evalúa la expresión de condición (en este caso, count <= 7), y el bucle solo se ejecuta si la condición es true. Por último, al final de cada iteración, se ejecuta la expresión de modificación. En el caso de la tabla de multiplicar del 7, la variable count se incrementa. El ejemplo 15-19 muestra cómo sería el código.

Ejemplo 15-19. Utilizando un bucle for

1
2
3
4
5
6
<script> for (count = 1; count <= 7; ++count) { document.write(count + "times 7 is " + count * 7 + "<br>"); } </script>

Al igual que en PHP, puedes asignar múltiples variables en el primer parámetro de un bucle for separándolas con una coma, así:

1
for (i = 1, j = 1; i < 10; i++)

Asimismo, puedes realizar múltiples modificaciones en el último parámetro, de esta forma:

1
for (i = 1; i < 10; i++, --j)

O puedes hacer ambas cosas al mismo tiempo:

1
for (i = 1, j = 1; i < 10; i++, --j)

Ruptura de un bucle

El comando break, que recordarás es importante dentro de una declaración switch, también está disponible dentro de los bucles for. Es posible que tengas que utilizar esto, por ejemplo, cuando busques algún tipo de coincidencia. Una vez que se encuentra la coincidencia, sabes que continuar solo sería una pérdida tiempo y harás que tu visitante tenga que esperar. El ejemplo 15-20 muestra cómo utilizar el comando break.

Ejemplo 15-20. Utilizando el comando break en un bucle for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script> haystack = new Array() haystack[17] = "Needle" for (j = 0; j < 20; ++j) { if (haystack[j] == "Needle") { document.write("<br>- Found at location " + j) break } else document.write(j + ", ") } </script>

Este script produce lo siguiente:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- Found at location 17

Declaración continue

A veces no quieres salir completamente de un bucle, sino que deseas omitir las sentencias restantes solo para una iteración concreta del bucle. En tales casos, puedes utilizar el comando continue. El ejemplo 15-21 muestra cómo se utiliza este comando.

Ejemplo 15-21. Utilizando el comando continue en un bucle for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script> haystack = new Array() haystack[4] = "Needle" haystack[11] = "Needle" haystack[17] = "Needle" for (j = 0; j < 20; ++j) { if (haystack[j] == "Needle") { document.write("<br>- Found at location " + j + "<br>") continue } document.write(j + ", ") } </script>

Nota cómo la segunda llamada a document.write no tiene que estar encerrada en una declaración else (como antes), porque el comando continue la omitirá si se ha encontrado una coincidencia. La salida de este script es la siguiente:

0, 1, 2, 3,
- Found at location 4
5, 6, 7, 8, 9, 10,
- Found at location 11
12, 13, 14, 15, 16,
- Found at location 17
18, 19,

Conversión explícita

A diferencia de PHP, JavaScript no tiene una conversión explícita (casting) de tipos de datos como (int) o (float). En su lugar, cuando necesites que un valor sea de un tipo de dato específico, utiliza una de las funciones integradas de JavaScript, que se muestran en la Tabla 15-6.

Tabla 15-6. Funciones de cambio de tipo en JavaScript

Cambiar al tipo Función que se utiliza
Int, Integer parseInt()
Bool, Boolean Boolean()
Float, Double, Real parseFloat()
String String()
Array split()

Entonces, por ejemplo, para cambiar un número de punto flotante a un entero, podrías utilizar un código como el siguiente (que muestra el valor 3):

1
2
3
n = 3.1415927 i = parseInt(n) document.write(i)

O puedes utilizar la forma compuesta:

1
document.write(parseInt(3.1415927))

Eso es todo sobre el flujo de control y las expresiones. El siguiente capítulo se centrará en el uso de funciones, objetos y arreglos en JavaScript.

Preguntas

  1. ¿Cómo se manejan los valores booleanos de manera diferente en PHP y JavaScript?
  2. ¿Qué caracteres se utilizan para definir un nombre de variable en JavaScript?
  3. ¿Cuál es la diferencia entre los operadores unarios, binarios y ternarios?
  4. ¿Cuál es la mejor manera de forzar la precedencia de operadores?
  5. ¿Cuándo utilizarías el operador === (identidad)?
  6. ¿Cuáles son las dos formas más simples de expresiones?
  7. Nombra los tres tipos de declaración de condicionales.
  8. ¿Cómo interpretan las declaraciones if y while las expresiones condicionales de diferentes tipos de datos?
  9. ¿Por qué un bucle for es más poderoso que un bucle while?
  10. ¿Cuál es el propósito de la declaración with?

Ver "Respuestas del Capítulo 15" del Apéndice A para comprobar las respuestas a estas preguntas.



Funciones, objetos y arrays en JavaScript

Al igual que PHP, JavaScript ofrece el acceso a funciones y objetos. De hecho, JavaScript está basado en objetos, porque, como has visto, tiene que acceder al DOM, lo que hace que cada elemento de un documento HTML esté disponible para manipularlo como un objeto.

El uso y la sintaxis también son bastante similares a los de PHP, por lo que deberías sentirte como en casa mientras te guío en el uso de funciones y objetos en JavaScript, así como en la exploración en profundidad del manejo de arreglos.

Funciones en JavaScript

Además de tener acceso a docenas de funciones (o métodos) integrados, como write, que ya has visto que se utiliza en document.write, puedes crear fácilmente tus propias funciones. Siempre que tengas un fragmento de código relativamente complejo que probablemente se reutilice, tienes un candidato para una función.

Definición de una función

La sintaxis general para una función se muestra aquí:

1
2
3
4
function function_name([parameter [, ...]]) { statements }

La primera línea de la sintaxis indica lo siguiente:

  • La definición comienza con la palabra function.
  • A continuación, sigue un nombre que debe comenzar con una letra o un guion bajo, seguido de cualquier número de letras, dígitos, signos de dólar o guiones bajos.
  • Los paréntesis son obligatorios.
  • Uno o más parámetros, separados por comas, son opcionales (indicados por los corchetes, que no forman parte de la sintaxis de la función).

Los nombres de las funciones son sensibles a mayúsculas, por lo que todos los strings a continuación se refieren a diferentes funciones: getInput, GETINPUT y getinput.

En JavaScript hay una convención general de nomenclaturas para funciones: la primera letra de cada palabra de un nombre se escribe en mayúsculas, excepto la primera letra, que se escribe en minúsculas. Por lo tanto, de los ejemplos anteriores, getInput sería el nombre preferido utilizado por la mayoría de los programadores. Esta convención se conoce comúnmente como bumpyCaps, bumpyCase, o (más frecuentemente) camelCase.

La llave de apertura inicia las instrucciones que se ejecutarán cuando llames a la función; una llave de cierre correspondiente debe cerrarla. Estas declaraciones pueden incluir una o más declaraciones de return, que obligan a la función a detener su ejecución y regresar al código que la llamó. Si se adjunta un valor a la declaración de return, el código que la llama puede recuperarlo.

El array arguments

El array arguments es un miembro de toda función. Con él, puedes determinar el número de variables pasadas a una función y cuáles son. Tomemos el ejemplo de una función llamada displayItems. El ejemplo 16-1 muestra una forma de escribirlo.

Ejemplo 16-1. Definición de una función

1
2
3
4
5
6
7
8
9
10
11
12
<script> displayItems("Dog", "Cat", "Pony", "Hamster", "Tortoise") function displayItems(v1, v2, v3, v4, v5) { document.write(v1 + "<br>") document.write(v2 + "<br>") document.write(v3 + "<br>") document.write(v4 + "<br>") document.write(v5 + "<br>") } </script>

Cuando llames a este script en tu navegador, mostrará lo siguiente:

Dog
Cat
Pony
Hamster
Tortoise

Todo esto está bien, pero ¿qué pasaría si quisieras pasar más de cinco elementos a la función? Además, reutilizar la llamada a document.write múltiples veces en lugar de emplear un bucle es un desperdicio de programación. Afortunadamente, el array arguments te da la flexibilidad para manejar un número variable de argumentos. El Ejemplo 16-2 muestra cómo puedes utilizarla para reescribir el ejemplo anterior de una manera mucho más eficiente.

Ejemplo 16-2. Modificando la función para utilizar el array arguments

1
2
3
4
5
6
7
8
9
10
11
<script> let c = "Car" displayItems("Bananas", 32.3, c) function displayItems() { for (j = 0; j < displayItems.arguments.length; ++j) document.write(displayItems.arguments[j] + "<br>") } </script>

Observa el uso de la propiedad length, que ya encontraste en el capítulo anterior, y también cómo hago referencia al array displayItems.arguments utilizando la variable j para desplazarnos sobre ella. También elegí mantener la función breve y concisa al no rodear el contenido del bucle for con llaves, ya que contiene solo una única instrucción. Recuerda que el bucle debe detenerse cuando j sea uno menos que length, no igual a length.

Usando esta técnica, ahora tienes una función que puede tomar tantos (o tan pocos) argumentos como desees y actuar sobre cada argumento como desees.

Devolviendo un valor

Las funciones no se utilizan solo para mostrar cosas. De hecho, se utilizan principalmente para realizar cálculos o manipulaciones de datos y luego devolver un resultado. La función fixNames en el Ejemplo 16-3 utiliza el array arguments (explicada en la sección anterior) para tomar una serie de strings que se le pasan y devolverlas como un solo string. La "corrección" que realiza es convertir todos los caracteres de los argumentos a minúsculas, excepto el primer carácter de cada argumento, que se convertirá a mayúsculas.

Ejemplo 16-3. Limpiando un nombre completo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script> document.write(fixNames("the", "DALLAS", "CowBoys")) function fixNames() { var s = "" for (j = 0; j < fixNames.arguments.length; ++j) s += fixNames.arguments[j].charAt(0).toUpperCase() + fixNames.arguments[j].substr(1).toLowerCase() + " " return s.substr(0, s.length - 1) } </script>

Cuando se llama con los parámetros the, DALLAS y CowBoys, por ejemplo, la función devuelve el string The Dallas Cowboys. Vamos a repasar la función.

Primero inicializa la variable temporal (y local) s con el string vacío. Luego, un bucle for itera a través de cada uno de los parámetros pasados, aislando el primer carácter del parámetro utilizando el método charAt y convirtiéndolo a mayúsculas con el método toUpperCase. Los distintos métodos mostrados en este ejemplo están todos integrados en JavaScript y disponibles por defecto.

Luego se utiliza el método substr para obtener el resto de cada string, que se convierte a minúsculas mediante el método toLowerCase. Una versión más completa del método substr, en este caso, especificaría cuántos caracteres son parte del substring como segundo argumento:

1
substr(1, (arguments[j].length) - 1 )

En otras palabras, este método substr dice: "Empieza con el carácter en la posición 1 (el segundo carácter) y devuelve el resto del string (la longitud menos uno)". Como un detalle agradable, sin embargo, el método substr asume que quieres el resto del string si omites el segundo argumento.

Después de convertir todo el argumento al caso deseado, se añade un carácter de espacio al final y el resultado se agrega a la variable temporal s.

Finalmente, se utiliza nuevamente el método substr para devolver el contenido de la variable s, excepto por el espacio final, que no se desea que aparezca. Lo eliminamos utilizando substr para devolver el string hasta el carácter final pero sin incluirlo.

1
fixNames.arguments[j].substr(1).toLowerCase()

Tienes que interpretar la expresión dividiéndola mentalmente en partes en los puntos. JavaScript evalúa estos elementos de la declaración de izquierda a derecha de la siguiente manera:

  1. Comienza con el nombre de la función en sí: fixNames.
  2. Extrae el elemento j del array arguments, elemento que representa los argumentos de fixNames.
  3. Invoca a substr con el valor del parámetro en 1 para el elemento extraído. El resultado pasa en su totalidad, menos el primer carácter, a la siguiente sección de la expresión.
  4. Aplica el método toLowerCase al string que se ha pasado hasta ahora.

Esta práctica a menudo se le conoce como encadenamiento de métodos. Entonces, por ejemplo, si el string mixedCASE se pasa a la expresión del ejemplo, pasará por las siguientes transformaciones:

mixedCASE
ixedCASE
ixedcase

En otras palabras, fixNames.arguments[j] produce “mixedCASE”, luego substr(1) toma “mixedCASE” y produce “ixedCASE”, y finalmente toLowerCase() toma “ixedCASE” y produce “ixedcase”.

Un recordatorio final: la variable s creada dentro de la función es local y, por lo tanto, no se puede acceder a ella fuera de la función. Al devolver s en la declaración return, hicimos que su valor estuviera disponible para el llamante, quien podría almacenarlo o utilizarlo de la forma que quisiera. Pero s en sí mismo desaparece al final de la función. Aunque podríamos hacer que una función opere sobre variables globales (y a veces eso es necesario), es mucho mejor simplemente devolver los valores que quieres preservar y dejar que JavaScript limpie el resto de variables utilizadas por la función.

Devolviendo un array

En el Ejemplo 16-3, la función devolvió un solo parámetro, pero ¿qué pasa si necesitas devolver varios parámetros? Puedes hacerlo devolviendo un array, como en el Ejemplo 16-4.

Ejemplo 16-4. Devolviendo un array de valores

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script> words = fixNames("the", "DALLAS", "CowBoys") for (j = 0; j < words.length; ++j) document.write(words[j] + "<br>") function fixNames() { var s = new Array() for (j = 0; j < fixNames.arguments.length; ++j) s[j] = fixNames.arguments[j].charAt(0).toUpperCase() + fixNames.arguments[j].substr(1).toLowerCase() return s } </script>

Aquí la variable words se define automáticamente como un array y se llena con el resultado que devuelve la llamada a la función fixNames. Luego, un bucle for itera a través del array y muestra cada elemento.

En cuanto a la función fixNames, es casi idéntica al Ejemplo 16-3, excepto que la variable s ahora es un array; después de procesar cada palabra, se almacena como un elemento de este array, que es devuelto por la declaración return.

Esta función permite la extracción de parámetros individuales de sus valores devueltos, como el siguiente (cuyo resultado es simplemente The Cowboys):

1
2
words = fixNames("the", "DALLAS", "CowBoys") document.write(words[0] + " " + words[2])

Objetos en JavaScript

Un objeto de JavaScript es un paso adelante al de una variable, que solo puede contener un valor a la vez. En cambio, los objetos pueden contener múltiples valores e incluso funciones. Un objeto agrupa datos junto con las funciones necesarias para manipularlos.

Declarando una clase

Al crear un script para utilizar objetos, necesitas diseñar una composición de datos y código llamado clase. Cada nuevo objeto basado en esta clase se llama instancia (o ocurrencia) de esa clase. Como ya has visto, los datos asociados a un objeto se llaman propiedades, mientras que las funciones que utiliza se llaman métodos.

Veamos cómo declarar la clase para un objeto llamado User que contendrá detalles sobre el usuario actual. Para crear la clase, simplemente escribe una función con el mismo nombre de la clase. Esta función puede aceptar argumentos (más adelante mostraré cómo se invoca) y puede crear propiedades y métodos para los objetos de esa clase. A la función se le llama constructor.

El ejemplo 16-5 muestra un constructor para la clase User con tres propiedades: forename (nombre), username (nombre de usuario) y password (contraseña). La clase también define el método showUser (mostrar usuario).

Ejemplo 16-5. Declaración de la clase User y su método

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script> function User(forename, username, password) { this.forename = forename this.username = username this.password = password this.showUser = function() { document.write("Forename: " + this.forename + "<br>") document.write("Username: " + this.username + "<br>") document.write("Password: " + this.password + "<br>") } } </script>

La función es diferente de otras funciones que hemos visto hasta ahora en varios aspectos:

  • Cada vez que se llama a la función, crea un nuevo objeto. De este modo, puedes llamar a la misma función una y otra vez con diferentes argumentos para crear usuarios con diferentes nombres, por ejemplo.
  • La función se refiere a un objeto llamado this, que se refiere a la instancia que se está creando. Como se muestra en el ejemplo, el objeto utiliza el nombre this para establecer sus propias propiedades, las cuales serán diferentes de un User a otro.
  • Se crea una nueva función llamada showUser dentro de la función. La sintaxis que se muestra aquí es nueva y bastante complicada, pero su propósito es vincular showUser a la clase User. Así, showUser se convierte en un método de la clase User.

La convención de nomenclatura que he utilizado es mantener todas las propiedades en minúsculas y usar al menos un carácter en mayúsculas en los nombres de los métodos, siguiendo la convención camelCase mencionada anteriormente en el capítulo.

El Ejemplo 16-5 sigue la forma recomendada para escribir un constructor de clase, que es incluir métodos en la función del constructor. Sin embargo, también puedes hacer referencia a funciones definidas fuera del constructor, como en el Ejemplo 16-6.

Ejemplo 16-6. Definición separada de una clase y un método

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script> function User(forename, username, password) { this.forename = forename this.username = username this.password = password this.showUser = showUser } function showUser() { document.write("Forename: " + this.forename + "<br>") document.write("Username: " + this.username + "<br>") document.write("Password: " + this.password + "<br>") } </script>

Te muestro esta forma porque seguramente lo encontrás al revisar el código de otros programadores.

Creando un objeto

Para crear una instancia de la clase User, puedes utilizar una declaración como la siguiente:

1
details = new User("Wolfgang", "w.a.mozart", "composer")

O puedes crear un objeto vacío, como este:

1
details = new User()

y luego completarlo más tarde, así:

1
2
3
details.forename = "Wolfgang" details.username = "w.a.mozart" details.password = "composer"

También puedes agregar nuevas propiedades a un objeto, así:

1
details.greeting = "Hello"

Puedes verificar que agregar las nuevas propiedades funcionan con la siguiente declaración:

1
document.write(details.greeting)

Accediendo a objetos

Para acceder a un objeto, puedes hacer referencia a sus propiedades, como en los siguientes dos ejemplos de declaraciones no relacionadas:

1
2
name = details.forename if (details.username == "Admin") loginAsAdmin()

Entonces, para acceder al método showUser de un objeto de la clase User, utilizarías la siguiente sintaxis, en la que el objeto details ya ha sido creado y completado con datos:

1
details.showUser()

Suponiendo los datos proporcionados anteriormente, este código mostraría lo siguiente:

Forename: Wolfgang
Username: w.a.mozart
Password: composer

La palabra reservada prototype

La palabra reservada prototype puede ahorrarte mucha memoria. En la clase User, cada instancia contendrá las tres propiedades y el método. Por lo tanto, si tienes mil de estos objetos en memoria, el método showUser también se replicará mil veces. Sin embargo, dado que el método es idéntico en todos los caso, puedes especificar que los nuevos objetos deben referirse a una única instancia del método en lugar de crear una copia de él. Entonces, en lugar de usar lo siguiente en un constructor de clase:

1
this.showUser = function()

podrías reemplazarlo con esto:

1
User.prototype.showUser = function()

El ejemplo 16-7 muestra cómo sería el nuevo constructor.

Ejemplo 16-7. Declarando una clase utilizando la palabra reservada prototype para un método

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script> function User(forename, username, password) { this.forename = forename this.username = username this.password = password User.prototype.showUser = function() { document.write("Forename: " + this.forename + "<br>") document.write("Username: " + this.username + "<br>") document.write("Password: " + this.password + "<br>") } } </script>

Esto funciona porque todas las funciones tienen una propiedad prototype, diseñada para contener propiedades y métodos que no se replican en ningún objeto creado a partir de una clase. En cambio, se pasan a sus objetos por referencia.

Esto significa que puedes agregar una propiedad o método prototype en cualquier momento y todos los objetos (incluso los ya creados) lo heredarán, como ilustran las siguientes declaraciones:

1
2
User.prototype.greeting = "Hello" document.write(details.greeting)

La primera declaración añade la propiedad prototype de greeting (saludo) con un valor de Hello (Hola) a la clase User. En la segunda línea, el objeto details, que ya ha sido creado, muestra correctamente esta nueva propiedad.

También puedes añadir o modificar métodos en una clase, tal y como se ilustran en las siguientes sentencias:

1
2
3
4
5
6
7
8
User.prototype.showUser = function() { document.write("Name " + this.forename + " User " + this.username + " Pass " + this.password) } details.showUser()

Podrías agregar estas líneas a tu script en una declaración condicional (como un if), para que se ejecuten si las actividades del usuario hacen que decidas que necesites un método showUser diferente. Después de que se ejecuten estas líneas, incluso si el objeto details ya ha sido creado, las llamadas posteriores a details.showUser ejecutarán la nueva función. La antigua definición de showUser se borrará.

Propiedades y métodos estáticos

Al leer sobre objetos en PHP, aprendiste que las clases pueden tener propiedades y métodos estáticos, así como propiedades y métodos asociados con una instancia particular de una clase. JavaScript también admite propiedades y métodos estáticos, que puedes almacenar y recuperar cómodamente desde la clase prototype. Así, las siguientes sentencias establecen y leen un string estático de User:

1
2
User.prototype.greeting = "Hello" document.write(User.prototype.greeting)

Extendiendo objetos de JavaScript

La palabra reservada prototype incluso te permite agregar funcionalidades a un objeto integrado. Por ejemplo, supongamos que te gustaría añadir la capacidad de reemplazar todos los espacios de un string por espacios no separables para evitar que se divida. Puedes hacer esto añadiendo un método prototype a la definición del objeto String predeterminado de JavaScript, así:

1
2
3
4
String.prototype.nbsp = function() { return this.replace(/ /g, '&nbsp;') }

Aquí se utiliza el método replace con una expresión regular para encontrar y reemplazar todos los espacios individuales con el string &nbsp;.

Nota

Si no estás familiarizado con las expresiones regulares, son una herramienta útil para extraer información o manipular strings y se explican con detalle en el Capítulo 17. Basta con decir que por ahora, puedes copiar y pegar los ejemplos anteriores y funcionarán como se describe, ilustrando el poder de extender los objetos String de JavaScript.

Si luego introduces el siguiente comando:

1
document.write("The quick brown fox".nbsp())

Saldrá el string The&nbsp;quick&nbsp;brown&nbsp;fox. O aquí tienes un método que puedes añadir que eliminará los espacios de principio y final del string (una vez más utilizando una expresión regular):

1
2
3
4
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, '') }

Si emites la siguiente declaración, la salida será el string Please trim me (sin los espacios del inicio y final):

1
document.write("Please trim me".trim())

Si dividimos la expresión en las partes que lo componen, los dos caracteres / marcan el inicio y el final de la expresión, y la g del final especifica una búsqueda global. Dentro de la expresión, la parte ^\s+ busca uno o más caracteres de espacios en blanco que aparezcan al inicio del string de búsqueda, mientras que la parte \s+$ busca uno o más caracteres de espacios en blanco al final del string de búsqueda. El carácter del medio | actúa para separar las dos alternativas.

El resultado es que cuando cualquiera de estas expresiones coincide, la coincidencia se reemplaza con un string vacío, devolviendo así una versión recortada del string sin espacios en blanco al inicio o al final.

Precaución

Existe un debate acerca de si extender objetos es una buena o mala práctica. Algunos programadores dicen que si más adelante se extiende un objeto para ofrecer oficialmente la funcionalidad que has añadido, podría implementarse de otra manera, o hacer algo bastante diferente a tu extensión, lo que podría causar un conflicto. Sin embargo, otros programadores, como el inventor de JavaScript, Brendan Eich, dice que esta es una práctica perfectamente aceptable. Mi opinión es que estoy de acuerdo con esto último, pero en código de producción elige nombres de extensiones que sean poco probables de ser utilizados oficialmente. Entonces, por ejemplo, la extensión trim podría renombrarse como mytrim, y el código de soporte podría escribirse de manera más segura como lo siguiente:

1
2
3
4
String.prototype.mytrim = function() { return this.replace(/^\s+|\s+$/g, '') }

Arrays en JavaScript

El manejo de arrays en JavaScript es muy similar al de PHP, aunque la sintaxis es un poco diferente. No obstante, dado que todo lo que ya has aprendido sobre arrays, esta sección debería ser relativamente sencilla para ti.

Arrays numéricos

Para crear un nuevo array, utiliza la siguiente sintaxis:

1
arrayname = new Array()

O puedes utilizar la forma abreviada, de la siguiente manera:

1
arrayname = []

Asignando valores a los elementos

En PHP, puedes agregar un nuevo elemento a un array simplemente asignándolo, sin especificar el desplazamiento del elemento, así:

1
2
$arrayname[] = "Element 1"; $arrayname[] = "Element 2";

Pero en JavaScript se utiliza el método push para lograr el mismo resultado, así:

1
2
arrayname.push("Element 1") arrayname.push("Element 2")

Esto te permite seguir añadiendo elementos a un array sin tener que llevar un control del número de elementos. Cuando necesites saber cuántos elementos hay en un array, puedes utilizar la propiedad length, así:

1
document.write(arrayname.length)

Opcionalmente, si deseas realizar tú mismo un seguimiento de las ubicaciones de los elementos y colocarlos en ubicaciones específicas, puedes utilizar una sintaxis como esta:

1
2
arrayname[0] = "Element 1" arrayname[1] = "Element 2"

El ejemplo 16-8 muestra un script simple que crea un array, lo carga con algunos valores y luego los muestra.

Ejemplo 16-8. Creación, construcción e impresión de un array

1
2
3
4
5
6
7
8
9
<script> numbers = [] numbers.push("One") numbers.push("Two") numbers.push("Three") for (j = 0; j < numbers.length; ++j) document.write("Element " + j + " = " + numbers[j] + "<br>") </script>

La salida de este script es la siguiente:

Element 0 = One
Element 1 = Two
Element 2 = Three

Asignación utilizando la palabra reservada Array

También puedes crear un array junto con algunos elementos iniciales utilizando la palabra reservada Array, así:

1
numbers = Array("One", "Two", "Three")

También no hay nada que te impida agregar más elementos después.

Ahora has visto un par de maneras de agregar elementos a un array, y una forma de referenciarlos. JavaScript ofrece muchos más, de los cuales hablaré en breve, pero primero, veremos otro tipo de array.

Arrays asociativos

Un array asociativo es aquel en el que los elementos se referencian por nombre en lugar de un desplazamiento por número entero. Sin embargo, JavaScript no soporta tales cosas. En su lugar, podemos lograr el mismo resultado creando un objeto con propiedades que actúen de la misma manera.

Entonces, para crear un "array asociativo," define un bloque de elementos dentro de unas llaves. Para cada elemento, coloca la clave a la izquierda y el contenido a la derecha de los dos puntos (:). El ejemplo 16-9 muestra cómo puedes crear un array asociativo para abarcar el contenido de la sección de "balls" (pelotas) de un minorista de equipamiento deportivo online.

Ejemplo 16-9. Creación y visualización de un array asociativo

1
2
3
4
5
6
7
8
9
<script> balls = {"golf": "Golf balls, 6", "tennis": "Tennis balls, 3", "soccer": "Soccer ball, 1", "ping": "Ping Pong balls, 1 doz"} for (ball in balls) document.write(ball + " = " + balls[ball] + "<br>") </script>

Para verificar que el array se ha creado y rellenado correctamente, he utilizado otro tipo de bucle for usando la palabra reservada in. Esto crea una nueva variable para usarlo únicamente dentro del array (ball, en este ejemplo) e itera a través de todos los elementos del array que se encuentra a la derecha de la palabra reservada in (balls, en este ejemplo). El bucle actúa sobre cada elemento de balls, colocando el valor de la clave en ball.

Utilizando este valor de la clave almacenado en ball, también puedes obtener el valor del elemento actual de balls. El resultado de llamar al script del ejemplo en un navegador es el siguiente:

golf = Golf balls, 6
tennis = Tennis balls, 3
soccer = Soccer ball, 1
ping = Ping Pong balls, 1 doz

Para obtener un elemento específico de un array asociativo, puedes especificar una clave explícitamente, de la siguiente manera (en este caso, mostrando el valor Soccer ball, 1):

1
document.write(balls['soccer'])

Arrays multidimensionales

Para crear un array multidimensional en JavaScript, simplemente coloca arrays dentro de otros arrays. Por ejemplo, para crear un array que contenga los detalles de un tablero de ajedrez bidimensional (8 × 8 casillas), podrías utilizar el código en el Ejemplo 16-10.

Ejemplo 16-10. Creando un array numérico multidimensional

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script> checkerboard = Array( Array(' ', 'o', ' ', 'o', ' ', 'o', ' ', 'o'), Array('o', ' ', 'o', ' ', 'o', ' ', 'o', ' '), Array(' ', 'o', ' ', 'o', ' ', 'o', ' ', 'o'), Array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '), Array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '), Array('O', ' ', 'O', ' ', 'O', ' ', 'O', ' '), Array(' ', 'O', ' ', 'O', ' ', 'O', ' ', 'O'), Array('O', ' ', 'O', ' ', 'O', ' ', 'O', ' ')) document.write("<pre>") for (j = 0; j < 8; ++j) { for (k = 0; k < 8; ++k) document.write(checkerboard[j][k] + " ") document.write("<br>") } document.write("</pre>") </script>

En este ejemplo, las letras minúsculas representan piezas negras, y las mayúsculas blancas. Un par de bucles for anidados recorren el array y muestran su contenido.

El bucle externo contiene dos sentencias, que están encerradas por llaves. El bucle interno luego procesa cada casilla en una fila, imprimiendo el carácter en la ubicación [j][k], seguido de un espacio (para alinear la impresión). Este bucle contiene una sola sentencia, por lo que no se requieren llaves para encerrarlo. Las etiquetas <pre> y </pre> aseguran que la salida se muestre correctamente, así:

  o   o   o   o 
o   o   o   o   
  o   o   o   o 
                
                
O   O   O   O   
  O   O   O   O 
O   O   O   O   

También puedes acceder directamente a cualquier elemento dentro de este array utilizando corchetes:

1
document.write(checkerboard[7][2])

Esta declaración imprime la letra mayúscula O, el octavo elemento hacia abajo y el tercero a lo largo, recuerda que los índices de los arrays comienzan en 0, no en 1.

Utilizando métodos de los arrays

Dada la potencia de los arrays, JavaScript viene preparado con una serie de métodos para manipularlos y también a sus datos. Aquí tienes una selección de los más útiles.

some

Cuando necesitas saber si al menos un elemento del array cumple con un cierto criterio, puedes utilizar la función some, que probará todos los elementos y se detendrá automáticamente, devolviendo el valor requerido tan pronto como uno coincida. Esto te ahorra tener que escribir tu propio código para realizar tales búsquedas, como este:

1
2
3
4
5
6
7
function isBiggerThan10(element, index, array) { return element > 10 } result = [2, 5, 8, 1, 4].some(isBiggerThan10) // result will be false result = [12, 5, 8, 1, 4].some(isBiggerThan10) // result will be true

indexOf

Para averiguar dónde se puede encontrar el elemento de un array, puedes llamar a la función indexOf en el array, que devolverá el índice del elemento encontrado (empezando desde 0), o -1 si no se encuentra. Por ejemplo, lo siguiente da como resultado el valor 2:

1
2
animals = ['cat', 'dog', 'cow', 'horse', 'elephant'] offset = animals.indexOf('cow')

concat

El método concat concatena dos arrays, o una serie de valores dentro de un array. Por ejemplo, el siguiente código produce Banana (Banana), Grape (Uva), Carrot (Zanahoria), Cabbage (Repollo):

1
2
3
4
fruit = ["Banana", "Grape"] veg = ["Carrot", "Cabbage"] document.write(fruit.concat(veg))

Puedes especificar múltiples arrays como argumentos, en cuyo caso concat agrega todos los elementos en el orden en que se especifican los arrays.

Aquí hay otra manera de utilizar concat. Esta vez, los valores simples se concatenan con el array pets (mascotas), lo que produce Cat (Gato), Dog (Perro), Fish (Pez), Rabbit (Conejo), Hamster (Hámster):

1
2
3
4
pets = ["Cat", "Dog", "Fish"] more_pets = pets.concat("Rabbit", "Hamster") document.write(more_pets)

forEach

El método forEach en JavaScript es otra manera de lograr una funcionalidad similar a la palabra reservada foreach de PHP. Para utilizarlo, le pasas el nombre de una función, que se llamará para cada elemento dentro del array. El ejemplo 16-11 muestra cómo.

Ejemplo 16-11. Utilizando el método forEach

1
2
3
4
5
6
7
8
9
10
<script> pets = ["Cat", "Dog", "Rabbit", "Hamster"] pets.forEach(output) function output(element, index, array) { document.write("Element at index " + index + " has the value " + element + "<br>") } </script>

En este caso, la función pasada a forEach se llama output. Toma tres parámetros: el elemento (element), su índice (index) y el array. Estos se pueden utilizar según lo requiera tu función. Este ejemplo muestra solo los valores del elemento (element) y el índice (index) utilizando la función document.write.

Una vez que se ha rellenado un array, el método se llama así:

1
pets.forEach(output)

Este es el resultado:

Element at index 0 has the value Cat
Element at index 1 has the value Dog
Element at index 2 has the value Rabbit
Element at index 3 has the value Hamster

join

Con el método join, puedes convertir todos los valores de un array a strings y luego unirlos en un gran string, colocando un separador opcional entre ellos. El ejemplo 16-12 muestra tres manera de utilizar este método.

Ejemplo 16-12. Utilizando el método join

1
2
3
4
5
6
7
<script> pets = ["Cat", "Dog", "Rabbit", "Hamster"] document.write(pets.join() + "<br>") document.write(pets.join(' ') + "<br>") document.write(pets.join(' : ') + "<br>") </script>

Sin un parámetro, join utiliza una coma para separar los elementos; de lo contrario, el string pasado a join se inserta entre cada elemento. La salida del Ejemplo 16-12 se ve así:

Cat,Dog,Rabbit,Hamster
Cat Dog Rabbit Hamster
Cat : Dog : Rabbit : Hamster

push y pop

Ya has visto cómo se puede utilizar el método push para insertar un valor en un array. El método inverso es pop. Elimina el elemento insertado más recientemente de un array y lo devuelve. El ejemplo 16-13 muestra un ejemplo de su uso.

Ejemplo 16-13. Utilizando los métodos push y pop

1
2
3
4
5
6
7
8
9
10
11
<script> sports = ["Football", "Tennis", "Baseball"] document.write("Start = " + sports + "<br>") sports.push("Hockey") document.write("After Push = " + sports + "<br>") removed = sports.pop() document.write("After Pop = " + sports + "<br>") document.write("Removed = " + removed + "<br>") </script>

Las tres declaraciones principales de este script se muestran en negritas. Primero, el script crea un array llamado sports (deportes) con tres elementos y luego agrega (push) un cuarto elemento al array. Después de eso, lo elimina (pop) de nuevo. En el proceso, se visualizan los valores existentes a través de document.write. El script muestra lo siguiente:

Start = Football,Tennis,Baseball
After Push = Football,Tennis,Baseball,Hockey
After Pop = Football,Tennis,Baseball
Removed = Hockey

Las funciones push y pop son útiles en situaciones donde necesitas desviarte de alguna actividad para hacer otra, y luego regresar. Por ejemplo, supongamos que quieres posponer algunas actividades para más tarde, mientras te ocupas de algo más importante ahora. Esto a menudo ocurre en la vida real cuando estamos revisando listas de "to-do" (tareas por hacer), así que emulemos eso en código, otorgando prioridad a las tareas número 2 y 5 en una lista de seis elementos, como en el Ejemplo 16-14.

Ejemplo 16-14. Utilizando push y pop dentro y fuera de un bucle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script> numbers = [] for (j = 1; j < 6; ++j) { if (j == 2 || j == 5) { document.write("Processing 'todo' #" + j + "<br>") } else { document.write("Putting off 'todo' #" + j + " until later<br>") numbers.push(j) } } document.write("<br>Finished processing the priority tasks.") document.write("<br>Commencing stored tasks, most recent first.<br><br>") document.write("Now processing 'todo' #" + numbers.pop() + "<br>") document.write("Now processing 'todo' #" + numbers.pop() + "<br>") document.write("Now processing 'todo' #" + numbers.pop() + "<br>") </script>

Por supuesto, aquí no se está procesando nada en realidad, solo se está enviando texto al navegador, pero ya entiendes la idea. La salida de este ejemplo es la siguiente:

Putting off 'todo' #1 until later
Processing 'todo' #2
Putting off 'todo' #3 until later
Putting off 'todo' #4 until later
Processing 'todo' #5

Finished processing the priority tasks.
Commencing stored tasks, most recent first.

Now processing 'todo' #4
Now processing 'todo' #3
Now processing 'todo' #1

Utilizando reverse

El método reverse simplemente invierte el orden de todos los elementos de un array. El ejemplo 16-15 muestra esto en acción.

Ejemplo 16-15. Utilizando el método reverse

1
2
3
4
5
<script> sports = ["Football", "Tennis", "Baseball", "Hockey"] sports.reverse() document.write(sports) </script>

El array original se modifica, y la salida de este script es la siguiente:

Hockey,Baseball,Tennis,Football

sort

Con el método sort, puedes colocar todos los elementos de un array en orden alfabético, dependiendo de los parámetros utilizados. El ejemplo 16-16 muestra cuatro tipos de ordenamiento.

Ejemplo 16-16. Utilizando el método sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script> // Alphabetical sort sports = ["Football", "Tennis", "Baseball", "Hockey"] sports.sort() document.write(sports + "<br>") // Reverse alphabetical sort sports = ["Football", "Tennis", "Baseball", "Hockey"] sports.sort().reverse() document.write(sports + "<br>") // Ascending numeric sort numbers = [7, 23, 6, 74] numbers.sort(function(a,b){return a - b}) document.write(numbers + "<br>") // Descending numeric sort numbers = [7, 23, 6, 74] numbers.sort(function(a,b){return b - a}) document.write(numbers + "<br>") </script>

La primera de las cuatro secciones del ejemplo utiliza el método sort predeterminado para realizar una ordenación alfabética, mientras que la segunda utiliza el método sort predeterminado y luego aplica el método reverse para obtener una ordenación alfabética inversa.

La tercera y cuarta sección son un poco más complicadas; utilizan una función para comparar la relación entre a y b. La función no tiene un nombre, porque solo se utiliza en el ordenamiento. Ya has visto la función llamada function usada para crear una función anónima; la usamos para definir un método en una clase (el método showUser).

Aquí, function crea una función anónima que satisface las necesidades del método sort. Si la función devuelve un valor mayor que cero, el ordenamiento asume que b viene antes que a. Si la función devuelve un valor menor que cero, el ordenamiento asume que a viene antes que b. El ordenamiento ejecuta esta función en todos los valores del array para determinar su orden. (Por supuesto, si a y b tienen el mismo valor, la función devuelve cero y no importa cuál valor esté primero.)

Al manipular el valor devuelto (a - b en contraste con b - a), la tercera y cuarta sección del Ejemplo 16-16 eligen entre una ordenación numérica ascendente y una ordenación numérica descendente.

Y, créelo o no, esto representa el final de tu introducción a JavaScript. Ahora deberías tener un conocimiento básico de las tres tecnologías principales cubiertas en este libro. El próximo capítulo se examinará algunas técnicas avanzadas utilizadas en estas tecnologías, como la coincidencia de patrones y la validación de entradas.

Preguntas

  1. ¿Son sensibles o insensibles a mayúsculas y minúsculas los nombres de funciones y variables en JavaScript?
  2. ¿Cómo puedes escribir una función que acepte y procese un número ilimitado de parámetros?
  3. Nombra una forma de devolver múltiples valores desde una función.
  4. Cuando estás definiendo una clase, ¿qué palabra reservada utilizas para referirte al objeto actual?
  5. ¿Todos los métodos de una clase tienen que estar definidos dentro de la definición de la clase?
  6. ¿Qué palabra reservada se utiliza para crear un objeto?
  7. ¿Cómo puedes hacer que una propiedad o método esté disponible para todos los objetos de una clase sin replicar la propiedad o método dentro del objeto?
  8. ¿Cómo puedes crear un array multidimensional?
  9. ¿Qué sintaxis se utiliza para crear un array asociativo?
  10. Escribe una instrucción para ordenar un array de números en orden numérico descendente.

Ver "Respuestas del Capítulo 16" del Apéndice A para comprobar las respuestas a estas preguntas.



Validación y manejo de errores en JavaScript y PHP

Validando la entrada del usuario con JavaScript



Utilizando comunicaciones asíncronas

¿Qué es la comunicación asíncrona?



Introducción a CSS

Importando una hoja de estilos



CSS avanzado con CSS3

Selectores de atributos



Accediendo a CSS desde JavaScript

Revisando la función getElementById



Introducción a jQuery

¿Por qué jQuery?



Introducción a jQuery Mobile

Incluyendo jQuery Mobile



Introducción a React

¿Para qué sirve React?



Introducción a HTML5

Canvas



Canvas de HTML5

Creando y accediendo a Canvas



Audio y vídeo en HTML5

Sobre los códecs



Otras características de HTML5

Geolocalización y el servicio de GPS



Uniendo todo

Diseñando una aplicación de redes sociales



Soluciones a las preguntas de los capítulos

Respuestas del capítulo 14

  1. Para incluir código JavaScript, utilizas las etiquetas <script> y </script>.
  2. Por defecto, el código JavaScript se mostrará en la parte del documento en la que reside. Si está en el encabezado, se mostrará en el head; si está en el cuerpo del documento, se mostrará en el body.
  3. Puedes incluir código JavaScript de otros archivos en tus documentos ya sea copiándolo y pegándolo o, lo más habitual, incluyéndolo como parte de una etiqueta <script src='filename.js'>.
  4. El equivalente de los comandos echo y print utilizados en PHP, es la función document.write de JavaScript (o método).
  5. Para crear un comentario en JavaScript, comienza con // para un comentario de una sola línea o incluirlo entre /* y */ para un comentario de varias líneas.
  6. El operador de concatenación de strings en JavaScript es el símbolo +.
  7. Dentro de una función de JavaScript, puedes definir una variable que tenga un alcance local iniciandola con la palabra reservada var , let o const en la primera asignación.
  8. Para mostrar la URL asignada al enlace con un id de thislink en los navegadores más importantes, puedes utilizar cualquiera de los dos siguientes comandos:
    1
    2
    document.write(document.getElementById('thislink').href) document.write(thislink.href)
  9. Los comandos para cambiar a la página anterior en el historial del navegador son:
    1
    2
    history.back() history.go(-1)
  10. Para reemplazar el documento actual con la página principal del sitio web de O'Reilly (https://www.oreilly.com), podrías utilizar el siguiente comando:
    1
    document.location.href = 'http://www.oreilly.com'

Respuestas del capítulo 15

  1. La diferencia más notable entre los valores booleanos de PHP y JavaScript es que PHP reconoce las palabras reservadas TRUE, true, FALSE y false, mientras que en JavaScript solo se admiten true y false. Además, en PHP, TRUE tiene un valor de 1, y FALSE es NULL; en JavaScript están representados por true y false, que pueden ser devueltos como valores de string.
  2. A diferencia de PHP, no se utiliza ningún carácter (como $) para definir el nombre de una variable en JavaScript. Los nombres de las variables en JavaScript pueden comenzar y contener letras con mayúsculas y minúsculas, así como guiones bajos; los nombres también pueden incluir dígitos, pero no el primer carácter.
  3. La diferencia entre los operadores unarios, binarios y ternarios es el número de operandos que cada uno requiere (uno, dos y tres, respectivamente).
  4. La mejor manera de forzar tu propia precedencia de operadores es rodear las partes de una expresión que deben evaluarse primero con paréntesis.
  5. Utilizas el operador de identidad cuando deseas evitar el cambio automático del tipo de dato del operando de JavaScript.
  6. Las formas más simples de expresiones son las literales (como números y cadenas) y las variables, que simplemente se evalúan a sí mismas.
  7. Los tres tipos de declaraciones condicionales son if, switch y el operador ?:.
  8. La mayoría de las expresiones condicionales en las declaraciones if y while son literales o booleanas y, por lo tanto, desencadenan la ejecución cuando se evalúan como true. Las expresiones numéricas desencadenan la ejecución cuando se evalúan a un valor distinto de cero. Las expresiones de string desencadenan la ejecución cuando se evalúan a un string no vacío. Un valor NULL se evalúa como false y, por lo tanto, no desencadena la ejecución.
  9. Los bucles que utilizan declaraciones for son más poderosos que los bucles while porque soportan dos parámetros adicionales para controlar el manejo del bucle.
  10. La declaración with toma un objeto como parámetro. Cuando la utilizamos, especificamos un objeto una sola vez; luego, para cada sentencia dentro del bloque with, se asume ese objeto.

Respuestas del capítulo 16

  1. Las funciones y los nombres de las variables en JavaScript son sensibles a mayúsculas y minúsculas. Las variables Count, count y COUNT son todas diferentes.
  2. Para escribir una función que acepte y procese un número ilimitado de parámetros, hay que acceder a los parámetros a través del array arguments, que es miembro de todas las funciones.
  3. Una forma de devolver múltiples valores desde una función es colocarlos todos dentro de un array y devolver el array.
  4. Al definir una clase, hay que utilizar la palabra reservada this para referirte al objeto actual.
  5. Los métodos de una clase no tienen que definirse dentro de la definición de la clase. Si un método se define fuera del constructor, el nombre del método debe asignarse al objeto this dentro de la definición de la clase.
  6. Los nuevos objetos se crean mediante la palabra reservada new.
  7. Puedes hacer que una propiedad o método esté disponible para todos los objetos de una clase sin replicarlo dentro del objeto utilizando la palabra reservada prototype para crear una única instancia, que luego se pasa por referencia a todos los objetos de la clase.
  8. Para crear un array multidimensional, hay que colocar subarrays dentro del array principal.
  9. La sintaxis que se utilizaría para crear un array asociativo es clave : valor, dentro de llaves, como en lo siguiente:
    1
    2
    3
    4
    5
    assocarray = { "forename" : "Paul", "surname" : "McCartney", "group" : "The Beatles" }
  10. Una sentencia para ordenar un array de números en orden numérico descendente se vería así:
    1
    numbers.sort(function(a, b){ return b a })