Introducción

Este libro trata de como hacer que las computadoras hagan lo que tú quieres que hagan. Las computadoras son tan comunes como los destornilladores hoy en día, pero tienen mucha más complejidad oculta y, por lo tanto, son más difíciles de operar y entender. Para muchos siguen siendo cosas extrañas, un poco amenazadoras.

Comunicándose con una computadora

Hemos encontrado dos formas efectivas de cerrar la brecha ente nosotros, suaves organismos biológicos con talento para el razonamiento social y espacial, y las computadoras, manipuladoras sin sentimientos de datos sin sentido. La primera es usar nuestros sentidos del mundo físico y construir interfaces que imitan ese mundo y nos permiten manipular figuras en una pantalla con nuestros dedos. Esto funciona muy bien para interacciones casuales con la máquina.

Pero aún no hemos encontrado una buena forma de usar la interfaz gráfica para comunicar a la computadora cosas que el diseñador de interfaces no anticipó. Para interfaces abiertas, como indicarle a la computadora que ejecute tareas arbitrarias, hemos tenido más suerte con otra estrategia, que hace uso de nuestro talento para el lenguaje: enseñarle a la computadora uno.

Los lenguajes humanos permiten que palabras y frases se combinen en muchas diferentes formas, lo cuál nos permite decir una amplia variedad de cosas. Los lenguajes computacionales, aunque son gramaticalmente menos flexibles, siguen un principio similar.

La computación casual se ha extendido mucho en los últimos 20 años, y las interfaces basadas en el lenguaje, que alguna vez fueron la forma predeterminada en la que las personas interactuaban con las computadoras, han sido reemplazadas en gran medida por interfaces gráficas. Pero todavía están ahí, si sabes donde buscar. Uno de tales lenguajes, JavaScript, está presente en casi todos los navegadores web existentes y por lo tanto, disponible en prácticamente todos los dispositivos de consumo.

Este libro trata de hacer que te familiarices lo suficiente con este lenguaje para que puedas hacer que la computadora haga lo que tú quieras.

Acerca de la Programación

No ilumino a aquellos que no están deseosos de aprender, tampoco despierto a quienes no están ansiosos de darse una explicación a sí mismos. Si les he presentado una esquina del cuadro y ellos no vienen con las otras tres, no debería recorrer otra vez los puntos."

Confucio

A parte de explicar JavaScript, te introduciré en los principios básicos de la programación. Programar, resulta, es difícil. Las reglas fundamentales típicamente son simples y claras. Pero los programas construidos sobre esas reglas tienden a volverse lo suficientemente complejos para introducir sus propias reglas y más complejidad. En cierta forma, estás construyendo tu propio laberinto y podrías perderte en él.

Habrá ocasiones en las que al leer este libro te sentirás terriblemente frustrado. Si eres nuevo programando, tendrás mucho material nuevo para digerir. Mucho de este material será después combinado en formas que requerirán que hagas conexiones adicionales.

Es tu responsabilidad realizar el esfuerzo necesario. Cuando se te haga difícil seguir este libro, no concluyas rápidamente nada acerca de tus capacidades. Tu eres bueno, sólo necesitas mantener el paso. Toma un respiro, vuelve a leer el material, y siempre asegúrate de leer y entender los programas de ejemplo y los ejercicios. Aprender es un trabajo duro, pero todo lo que aprendas ahora es tuyo y hará el aprendizaje cada vez más fácil.

El programador de computadoras es el creador de universos de los cuales él sólo es responsable. Universos de complejidad virtualmente ilimitada pueden ser creados en la forma de programas de computadora."

Joseph Weizenbaum, Computer Power and Human Reason

Un programa es muchas cosas. Es una pieza de texto escrita por un programador, es la fuerza que dirige a la computadora para hacer lo que hace, son datos en la memoria de la computadora, y aún así controla las acciones realizadas en esta misma memoria. Las analogías que tratan de comparar a las computadoras con objetos que conocemos tienden a quedarse cortas. Una que se ajusta superficialmente es la de máquina, un montón de piezas separadas que se relacionan, y para hacerlo funcionar, tenemos que considerar las formas en que esas piezas se interconectan y contribuyen al funcionamiento del todo.

Una computadora es una máquina que actuá como anfitriona de estas máquinas inmateriales. Las computadoras por sí mismas sólo pueden hacer cosas estúpidamente simples. La razón por la que son tan poderosas es que hacen esas cosas a una velocidad increíblemente rápida. Un programa puede combinar ingeniosamente un número enorme de esas acciones simples para lograr cosas muy complicadas.

Para algunos de nosotros, escribir programas de computadoras es un juego fascinante. Un programa es una construcción del pensamiento. No tiene costo construirlo, no pesa nada, y crece fácilmente bajo nuestras manos tecleando.

Pero si no tenemos cuidado, el tamaño y la complejidad de un programa se saldrán de control, confundiendo incluso a la persona que lo creó. Mantener los programas bajo control es el principal problema de la programación. Cuando funcionan, es hermoso. El Arte de programar es la habilidad de controlar la complejidad. Un gran programa está dominado, hecho simple en su complejidad.

Muchos programadores creen que esta complejidad es mejor controlada usando sólo un pequeño conjunto de técnicas bien entendidas en sus programas. Estos han compuesto reglas estrictas (“mejores prácticas”) que prescriben la forma que los programas deberían tener, y los más celosos de ellos considerarán a aquellos que se salen de esta pequeña zona segura como malos programadores.

¡Qué hostilidad hacia la riqueza de la programación, la de tratar de reducirla a algo simple y predecible, tratar de hacer tabú a todos los programas extraños y bellos! El panorama de todas las técnicas de programación es enorme, fascinante en su diversidad, y permanece inexplorado en gran parte. Ciertamente es peligroso ir, porque seduce al programador novato con todo tipo de confusiones, pero eso sólo significa que debes de andar con cuidado y estar alerta. Conforme vayas aprendiendo, siempre habrá nuevos retos y nuevo territorio por explorar. Los programadores que se nieguen a explorar dejarán de progresar, olvidarán su alegría, y se aburrirán con su trabajo.

Por qué el lenguaje importa

En el principio, cuando nació la computación, no había lenguajes de programación. Los programas lucían algo así:

00110001 00000000 00000000
00110001 00000001 00000001
00110011 00000001 00000010
01010001 00001011 00000010
00100010 00000010 00001000
01000011 00000001 00000000
01000001 00000001 00000001
00010000 00000010 00000000
01100010 00000000 00000000

Eso es un programa para sumar los números del 1 al 10 e imprimir el resultado: 1 + 2 + ... + 10 = 55. Podría correr en una simple, hipotética máquina. Para programar las primeras computadoras, era necesario configurar grandes conjuntos de tiras de switches en la posición correcta o perforar tiras de tarjetas e introducirlas en la computadora. Probablemente te puedes imaginar cuan tedioso y propenso al error era este procedimiento. Incluso escribir programas simples requería gran inteligencia y disciplina. Los programas complejos eran casi inconcebibles.

Claro, introducir manualmente estos oscuros patrones de bits (los unos y ceros) dieron al programador un profundo sentimiento de ser un poderoso mago. Y eso ha valido algo en términos de satisfacción en el trabajo.

Cada línea del programa anterior contiene una instrucción. Podría ser escrita en español como sigue:

1. Guarda el número 0 en la dirección de memoria 0.
2. Guarda el número 1 en la dirección de memoria 1.
3. Guarda el valor de la dirección de memoria 1 en la dirección 2.
4. Resta 11 del valor en la dirección de memoria 2.
5. Si el valor en la dirección de memoria 2 es el número 0,
   continúa con la instrucción 9.
6. Suma el valor de la dirección de memoria 1 al valor de la
   dirección de memoria 0.
7. Suma 1 al valor de la dirección de memoria 1.
8. Continúa con la instrucción 3.
9. Devuelve el valor de la dirección de memoria 0.

Aunque eso es más legible que una sopa de bits, sigue sin ser agradable. Podría ayudar usar nombres en los números para las instrucciones y direcciones de memoria.

 Pon “total” igual a 0.
 Pon “conteo” igual a 1.
[bucle]
 Pon “comparación” igual a “conteo”.
 Resta 11 de “comparación”.
 Si “comparación” es cero, continúa en [final].
 Suma “conteo” a “total”.
 Suma 1 a “conteo”.
 Continúa en [bucle].
[final]
 Devuelve “total”.

¿Puedes entender cómo funciona el programa en este punto? Las primeras dos líneas ponen en dos locaciones de memoria sus valores iniciales: total será usado para construir el resultado del cálculo y conteo mantendrá el registro del número en el que estamos trabajando en este momento. Las líneas que usan comparación son probablemente las más raras. El programa quiere ver si conteo es igual a 11 para saber si puede terminar. A causa de que nuestra máquina hipotética es más bien primitiva, solo puede probar si un número es cero y tomar una decisión (o salto) basada en eso. Así que usa la dirección de memoria etiquetada como comparación para calcular el valor de conteo - 11 y toma una decisión basada en ese valor. Las próximas dos líneas suman el valor de conteo al resultado e incrementan conteo en 1 cada vez que el programa ha decido que conteo no es todavía 11.

Este es el mismo programa en JavaScript:

var total = 0, conteo = 1;
while (conteo <= 10) {
  total += conteo;
  conteo += 1;
}
console.log(total);
// → 55

Esta versión nos da unas cuantas mejoras más. Y lo más importante es que ya no hay necesidad de especificar la forma en que queremos que nuestro programa salte de atrás para adelante. La construcción del lenguaje while se encarga de eso. Continúa ejecutando el bloque (dentro de las llaves) debajo de él mientras la condición que se le dio se mantenga. Esa condición es conteo <= 10, lo que significa "conteo es menor o igual que 10". Ya no tenemos que crear un valor temporal y compararlo con 0, lo cuál era un detalle sin interés para nosotros. Parte del poder de los lenguajes de programación es que estos se encargan de los detalles que no nos interesan.

Al final del programa, después de que la construcción while ha terminado, la operación console.log es aplicada al resultado para imprimirlo como resultado.

Finalmente, así es como el programa luciría si sucediera que tenemos las convenientes operaciones range y sum disponibles, una crea una colección de números dentro de un rango y la otra calcula la suma de una colección de números, respectivamente:

console.log(sum(range(1, 10)));
// → 55

La moraleja de esta historia es que el mismo programa puede ser expresado en formas largas, cortas, legibles e ilegibles. La primera versión del programa era extremadamente difícil de entender, mientras que la última está casi en lenguaje humano, inglés: log(registra) la sum(suma) del rango de números del 1 al 10. (Veremos en capítulos posteriores como construir operaciones como sum y range.)

Un buen lenguaje de programación ayuda al programador mediante permitirle hablar acerca de las acciones que la computadora tiene que realizar en un nivel más alto. Ayuda a omitir detalles que no nos interesan, provee convenientes bloques de construcción (tales como while y console.log), y te permite definir tus propios bloques (como sum y range), y hace fácil componer esos bloques.

¿Qué es JavaScript?

JavaScript fue introducido en 1995 como una forma de añadir programas a las páginas web en el navegador Netscape Navigator. Desde entonces el lenguaje ha sido adoptado por la mayoría de los navegadores más importantes. Ha hecho posibles las aplicaciones web modernas, aplicaciones con las que puedes interactuar directamente, sin hacer recarga de la página para cada acción. Pero también es usado en sitios web más tradicionales para añadirles distintas formas de interactividad y hacerlos más ingeniosos.

Es importante hacer notar que JavaScript no tiene casi nada que ver con el lenguaje de programación llamado Java. El nombre tan parecido fue inspirado por razones de marketing más que de buen juicio. Cuando JavaScript estaba entrando, el lenguaje Java estaba siendo promovido fuertemente y ganando popularidad. Alguien pensó que sería buena idea colgarse de su éxito. Ahora ya ya nos quedamos con el nombre.

Después de su adopción fuera de Netscape, un documento de estándar fue escrito para describir la forma en que JavaScript debería de trabajar para asegurarse de que distintos programas que argumentaban soportar JavaScript hablaran realmente del mismo lenguaje. Este documento es llamado el estándar ECMAScript, en honor a la Ecma International Organization, que realizó la estandarización. En la práctica, los términos ECMAScript y JavaScript pueden ser usados indistintamente, son dos nombres para el mismo lenguaje.

Existen aquellos que dirán cosas terribles acerca de JavaScript. Muchas de esas cosas son ciertas. La primera vez que tuve que programar algo en JavaScript, rápidamente llegué a despreciarlo. Aceptaría cualquier cosa que yo escribiera pero la interpretaba en una forma completamente distinta a lo que yo quería decir. Esto tenía mucho que ver con el hecho de que yo no tenía idea de lo que estaba haciendo, por supuesto, pero aquí existe un problema real: JavaScript es extremadamente liberal en lo que permite. La idea detrás de este diseño es que haría la programación en JavaScript más fácil para los principiantes. En realidad, la mayor parte de las veces eso hace más difícil encontrar los errores en tus programas debido a que el sistema no te los señalará.

Esta flexibilidad tiene sus ventajas también. Permite muchas técnicas que son imposibles en otros lenguajes más rígidos, y como verás, puede ser usada para superar algunas de las fallas de JavaScript (por ejemplo en el Capítulo 10). Después de aprender el lenguaje propiamente y de trabajar con él por un tiempo, JavaScript realmente me ha gustado.

Han existido varias versiones de JavaScript. ECMAScript versión 3 fue la versión ampliamente soportada en la época de ascensión a la dominación de JavaScript, más o menos entre 2000 y 2010. Durante este tiempo, el trabajo fue dirigido a una ambiciosa versión 4, que planeaba varias mejoras radicales y extensiones al lenguaje. Cambiar un lenguaje vivo, ampliamente usado en una forma tan radical resultó ser políticamente difícil, y el trabajo en la versión 4 fue abandonado en 2008, llevando así a la salida de la mucho menos ambiciosa versión 5 en 2009. Nosotros estamos en el punto en el que todos los navegadores mayores soportan la versión 5, que es la versión en la que este libro se enfocará. La versión 6 está en proceso de ser terminada, y algunos navegadores están empezando a soportar nuevas características de esta versión.

Los navegadores web no son las únicas plataformas en las que JavaScript es usado. Algunas Bases de Datos, como MongoDB y CouchDB, usan JavaScript como su lenguaje de manejo y consulta. Varias plataformas para programación de computadoras de escritorio y servidores, más notablemente el proyecto Node.js (el tema del Capítulo 20), están haciendo disponible un entorno poderoso para la programación en JavaScript fuera del navegador.

Código, y qué hacer con él

El código es el texto del que están compuestos los programas. La mayor parte de los capítulos de este libro contienen un montón de él. En mi experiencia, leer y escribir código son partes indispensables de aprender a programar, así que trata de no sólo darles una mirada rápida a los ejemplos. Léelos atentamente y entiéndelos. Esto podría ser lento y confuso al principio, pero prometo que rápidamente le agarrarás el modo. Lo mismo es aplicable a los ejercicios. No asumas que los entiendes hasta que realmente hayas escrito una solución que funcione.

Te recomiendo probar tus soluciones a los ejercicios en un intérprete de JavaScript real. De esa forma obtendrás retroalimentación inmediata acerca de si lo que estás haciendo funciona, y, yo espero, serás tentado a experimentar e ir más allá de los ejercicios.

Cuando estés leyendo este libro en tu navegador, puedes editar(y correr) todos los programas de ejemplo haciendo clic en ellos.

Si quieres correr los programas de este libro fuera del ambiente que se provee, hay que prestarle atención a ciertas cosas. Muchos ejemplos deberían trabajar por sí mismos. Pero el código de los capítulos más avanzados está escrito para un entorno específico (el navegador o Node.js) y sólo puede correr ahí. Además, muchos capítulos definen programas más grandes, y las partes del código que aparecen en él dependen de entre ellas o de archivos externos. El entorno en el sitio tiene links para descargar los archivos Zip que contienen todos los scripts y datos necesarios para hacer funcionar el código de cualquier capítulo.

Vista general del libro

Este libro está compuesto por tres partes. Los primeros 11 capítulos hablan de JavaScript en sí mismo. Los siguientes ocho son acerca de los navegadores web y la forma en que JavaScript es usado para programarlos. Finalmente, los últimos dos capítulos están dedicados a Node.js, otro entorno para programar en JavaScript.

A lo largo del libro hay cinco capítulos de proyecto, que describen programas de ejemplo más grandes para darte una prueba de la programación en el mundo real. En orden de aparición trabajaremos en simulación de vida artificial, un lenguaje de programación, un juego de plataforma, un programa de pintura, y un sitio dinámico.

La parte del lenguaje del libro empieza con cuatro capítulos para presentar la estructura básica de JavaScript. Estos presentan estructuras de control (como la palabra while que viste en esta introducción), funciones (escribir tus propias operaciones), y estructuras de datos. Después de esto, serás capaz de escribir programas simples. Después, los capítulos 5 y 6 presentan técnicas para usar funciones y objetos para escribir código más abstracto y de esta manera mantener a la complejidad bajo control.

Después de un primer capítulo de proyecto, la primera parte del libro continúa con capítulos acerca de manejo y corrección de errores, expresiones regulares (una herramienta importante para el manejo de datos de texto), y modularidad, otra arma contra la complejidad. El segundo capítulo de proyecto termina con la primera parte del libro.

En la segunda parte, los Capítulos 12 a 19, describen las herramientas a las que JavaScript tiene acceso en el navegador web. Aprenderás a mostrar cosas en la pantalla (Capítulos 13 y 16), responder a los datos de entrada del usuario (Capítulos 14 y 18), y a comunicarte a través de la red (Capítulo 17). Otra vez, hay dos proyectos en esta parte.

Después de eso, el Capítulo 20 describe Node.js, y el Capítulo 21 construye un sencillo sistema web usando esa herramienta.

Convenciones Tipográficas

En este libro, texto escrito en fuente monoespacio representará elementos de programas; algunas veces programas completos y otras, partes de programas que hayan sido definidos cerca de ahí. Los programas(de los cuales has visto unos pocos), están escritos como sigue:

function fac(n) {
  if (n == 0)
    return 1;
  else
    return fac(n - 1) * n;
}

Algunas veces, para mostrar la salida que un programa produce, la salida esperada será escrita después de este, con dos diagonales y una flecha enfrente.

console.log(fac(8));
// → 40320

¡Buena suerte!