JavaScript para Gatos
JavaScript para Gatos
Gatos
Una introducción para nuevos programadores
Tan simple que hasta tu
amigo humano puede
también hacerlo!
JavaScript es un lenguaje de
programación o, en otras
palabras, un medio por el cual la
computadora es instruída para
hacer cosas. Así como cualquiera
de nosotros controlamos a los
humanos con silbidos y maullidos,
uno puede controlar
computadoras con enunciados
escritos en un lenguaje de
programación. Todos los
navegadores web entienden
JavaScript y tu puedes tomar ventaja de eso para hacer que las páginas web hagan cosas locas!
JavaScript empezó como una manera de hacer páginas web más interactivas. Hoy en día JavaScript corre
no solo en navegadores — también corre en servidores web, teléfonos y hasta robots! Esta página te va a
enseñar una base de JavaScript para que puedas arrancar instantáneamente*.
* Tiempo real del tutorial: Más que instantáneo. Probablemente una hora o dos. Además como sos un gato
te debe gustar más estar tirado al sol que corriendo.
Tabla de contenidos
La base
Strings
Valores y variables
Usando funciones
Funciones del lenguaje
Código de terceros
Creando nuevas funciones
Ciclos
Arrays
Objetos
Callbacks
Lectura recomendada
Es por eso que no tienes que ser un gato miedoso! La peor cosa que puede pasar es que tengas que
refrescar esta página en tu navegador web si estás atascado. Tampoco te preocupes, esto pasa muy rara
vez.
# La base
Hay JavaScript corriendo en esta página en este momento. Juguemos un poco con eso. Por simplicidad
voy a asumir que estás usando Google Chrome para leer esta página (si no es así va a ser probablemente
más fácil para los dos si sigues el tutorial usando Chrome).
Primero, haz click derecho en cualquier parte de la pantalla y selecciona Inspeccionar elemento (o
Inspect element en inglés), después click en el tab que dice Console. Deberías ver una cosa que se
parece a esto:
Esta es una consola, también llamada "línea de comando" o "terminal". Básicamente es una forma de
escribir una cosa a la vez en la computadora e inmediatamente obtener la respuesta. Existen
herramientas de aprendizaje súper útiles (Yo todavía uso la consola casi todos los días que escribo
código).
La consola hace algunas cosas realmente geniales. Comencé escribiendo algo y la consola está
ayudandome dandome una lista de todas las posibles cosas que puedo continuar escribiendo! Otra cosa
que puedes hacer es escribir 1 + 1 en la consola y después apretar Enter y ver que pasa.
var es una abreviatura de variable y el símbolo = significa guarda la cosa del lado derecho en la cosa
del lado izquierdo. Además como puedes ver, ahora que estamos guardando nuestra sentencia en una
variable la consola no devuelve la sentencia, sino que nos da undefined como respuesta, lo que significa
no hay nada para devolver.
Si simplemente escribes el nombre de una variable en la consola va a imprimir el valor guardado en esa
variable. Una nota sobre las variables es que por defecto se pierden cuando cambias a una página
diferente. Si fuera a refrescar la página en Chrome, por ejemplo, mi variable sentenciaPerro
desaparecería para siempre, como si nunca hubiera existido. Pero no te preocupes por esto demasiado —
puedes apretar las flechas para arriba y abajo en el teclado cuando estás en la consola y obtener las
sentencias que fuiste escribiendo últimamente.
# Usando funciones
Ahora que tenemos nuestra sentencia guardada en una variable, vamos a cambiar la palabra guardada en
ella! Podemos hacer esto creando una función. Las funciones son un tipo de valor que realiza justamente
una función específica (También conocido como propósito o acción) por nosotros. Llamarlas "acciones"
suena extraño y supongo que por eso eligieron "función" en su lugar.
JavaScript tiene una función llamada replace (reemplazar en inglés) que hace exactamente lo que
queremos! Las funciones toman valores en sus paréntesis (cero, uno o más) y devuelve o bien nada
( undefined ) o el string modificado. La función replace está disponible para usar sobre cualquier string y
toma 2 valores: los caracteres que queremos sacar y los caracteres que los van a reemplazar. Se torna un
poco confuso describir estas cosas así que acá tenemos un ejemplo visual:
Notas como el valor de sentenciaPerro es el mismo incluso después de correr replace sobre él? Esto se
debe a que la función replace , (y la mayoría de funciones de JavaScript para estos propósitos) toman el
valor que le damos y retornan un nuevo valor, sin modificar el valor que le pasamos. Como no queremos
guardar el resultado (no hay = en el lado izquierdo de la operación de reemplazo) se imprime el valor
retornado en la consola.
# Código de terceros
También existe un montón de código JavaScript disponible que no forma parte de la biblioteca estándar.
Se suele referir al JavaScript escrito por tercero como una "biblioteca" o "plugin". Uno de mis favoritos se
llama Underscore.js. Vayamos a buscarlo y cargarlo en nuestra página! Primero ve al sitio de
Underscore, http://underscorejs.org/, haz click en el link de descarga (En general uso la versión de
desarrollo porque son fáciles de leer pero cualquiera de las 2 te va a dar la misma funcionalidad), y copia
todo el código en tu portapapeles (puedes usar Seleccionar todo haciendo click derecho). Después
var es una abreviatura de variable y el símbolo = significa guarda la cosa del lado derecho en la cosa
del lado izquierdo. Además como puedes ver, ahora que estamos guardando nuestra sentencia en una
variable la consola no devuelve la sentencia, sino que nos da undefined como respuesta, lo que significa
no hay nada para devolver.
Si simplemente escribes el nombre de una variable en la consola va a imprimir el valor guardado en esa
variable. Una nota sobre las variables es que por defecto se pierden cuando cambias a una página
diferente. Si fuera a refrescar la página en Chrome, por ejemplo, mi variable sentenciaPerro
desaparecería para siempre, como si nunca hubiera existido. Pero no te preocupes por esto demasiado —
puedes apretar las flechas para arriba y abajo en el teclado cuando estás en la consola y obtener las
sentencias que fuiste escribiendo últimamente.
# Usando funciones
Ahora que tenemos nuestra sentencia guardada en una variable, vamos a cambiar la palabra guardada en
ella! Podemos hacer esto creando una función. Las funciones son un tipo de valor que realiza justamente
una función específica (También conocido como propósito o acción) por nosotros. Llamarlas "acciones"
suena extraño y supongo que por eso eligieron "función" en su lugar.
JavaScript tiene una función llamada replace (reemplazar en inglés) que hace exactamente lo que
queremos! Las funciones toman valores en sus paréntesis (cero, uno o más) y devuelve o bien nada
( undefined ) o el string modificado. La función replace está disponible para usar sobre cualquier string y
toma 2 valores: los caracteres que queremos sacar y los caracteres que los van a reemplazar. Se torna un
poco confuso describir estas cosas así que acá tenemos un ejemplo visual:
Notas como el valor de sentenciaPerro es el mismo incluso después de correr replace sobre él? Esto se
debe a que la función replace , (y la mayoría de funciones de JavaScript para estos propósitos) toman el
valor que le damos y retornan un nuevo valor, sin modificar el valor que le pasamos. Como no queremos
guardar el resultado (no hay = en el lado izquierdo de la operación de reemplazo) se imprime el valor
retornado en la consola.
# Código de terceros
También existe un montón de código JavaScript disponible que no forma parte de la biblioteca estándar.
Se suele referir al JavaScript escrito por tercero como una "biblioteca" o "plugin". Uno de mis favoritos se
llama Underscore.js. Vayamos a buscarlo y cargarlo en nuestra página! Primero ve al sitio de
Underscore, http://underscorejs.org/, haz click en el link de descarga (En general uso la versión de
desarrollo porque son fáciles de leer pero cualquiera de las 2 te va a dar la misma funcionalidad), y copia
todo el código en tu portapapeles (puedes usar Seleccionar todo haciendo click derecho). Después
pegalo en tu consola y apretá enter. Ahora tu navegador tiene una nueva variable: _ . Underscore te da
una gran cantidad de funciones útiles para jugar. Vamos a aprender a usarlas más adelante.
function ponerleOnda(string) {
return string + '!!!!'
}
En mi cabeza lo leo en voz alta como: "hay una función llamada 'ponerle onda' que toma un string y
devuelve una nueva copia del string que tiene algunos puntos de exclamación al final". Así es como
escribo esto en la consola manualmente sin escribir la función:
La expresión string + !!!! devuelve un nuevo string y nuestra variable llamada string queda igual que
antes (ya que nunca la actualizamos usando = ).
Usemos nuestra función en vez de hacerlo manualmente. Primero, pega la función en la consola y
después llama a la función pasandole un string:
Los elementos (así es como llamas a un item de un Array) son guardados en arrays empezando por el 0 y
contando para arriba. Entonces misAmigosGatos[0] devuelve felix y misAmigosGatos[1] devuelve
sessa ... etc etc.
Para obtener un amigo de tu nuevo array puedes simplemente accederlo directamente así:
console.log(misAmigosGatos[0])
Si hiciste un nuevo amigo en el club gatuno de moda la otra noche y quieres agregarlo a tu lista es super
simple: misAmigosGatos.push("gato de moda") .
Para verificar que el nuevo gato está adentro de tu array puedes usar .length :
Notaste que push devolvió el tamaño? Buenisimo! También toma nota que los arrays siempre preservan
el orden lo que significa que van a recordar el orden en el que agregaste o definiste las cosas. No todo en
JavaScript preserva el orden así que recuerda esta propiedad especial de los Arrays!
# Objetos
Los Arrays son buenos para listar, pero para otras tareas puede ser duro trabajar con ellos. Considera
nuestro array de amigos felinos. Qué pasa si quieres guardar más que nombres?
Esto puede ser frágil porque nuestro arrays cambian y agregamos un nuevo gato al comienzo podemos
también actualizar la variable posicionDeFelix apuntando a la nueva ubicación de la información de Felix
en los arreglos! Acá mostramos una forma más fácil de mantener guardada la información usando objetos:
var primerGato = { nombre: "felix", apellido: "el gato", dirección: "La calle" }
var segundoGato = { nombre: "sessa", lastName: "gato", direccion: "Liniers" }
var tercerGato = { nombre: "garfield", apellido: "gato", direccion: "Casa de John Bonachón" }
Por qué lo haríamos de esta manera? Porque ahora tenemos una variable para cada gato que podemos
usar a la hora de obtener valores del gato de una manera más conveniente y legible.
Puedes pensar a los Objetos como llaves de un llavero. Cada una es para una puerta en particular y si
tienes lindas etiquetas en tus llaves puedes abrir puertas muy rápidamente. De hecho, las cosas del lado
izquierdo del : son llamadas claves (también se conocen como propiedades) y las cosas del lado
derecho se llaman valores.
Si tuvieramos que hacer manualmente lo que hace times se vería así:
imprimirNumero(0)
imprimirNumero(1)
imprimirNumero(2)
imprimirNumero(3)
imprimirNumero(4)
imprimirNumero(5)
imprimirNumero(6)
imprimirNumero(7)
imprimirNumero(8)
imprimirNumero(9)
Pero los gatos rechazan hacer trabajo manual innecesario como ese, entonces siempre debemos
preguntarnos, "estamos haciendo esto del modo más vago posible?"
Entonces por qué se llama esto ciclado? Pensalo de esta manera: Si tuvieramos que escribir una lista de
10 números (de 0 a 9) usango un Array de JavaScript se vería como esto:
Lo que times realmente hace es visitar cada número y repetir la tarea: en el ejemplo de arriba la tarea
era llamar a la función imprimirNumero con el número actual. Repetir tareas de ese modo se llama ciclar
sobre el Array.
# Arrays
Los mencioné unas cuantas veces pero pasemos un minuto aprendiendo sobre ellos. Imagina que
necesitas hacer un seguimiento de tus amigos. Bueno, un Array lo va a hacer bien. Piensa en un Array
como una lista ordenada donde puedes mantener una gran cantidad de cosas adentro.
Para obtener un amigo de tu nuevo array puedes simplemente accederlo directamente así:
console.log(misAmigosGatos[0])
Si hiciste un nuevo amigo en el club gatuno de moda la otra noche y quieres agregarlo a tu lista es super
simple: misAmigosGatos.push("gato de moda") .
Para verificar que el nuevo gato está adentro de tu array puedes usar .length :
Notaste que push devolvió el tamaño? Buenisimo! También toma nota que los arrays siempre preservan
el orden lo que significa que van a recordar el orden en el que agregaste o definiste las cosas. No todo en
JavaScript preserva el orden así que recuerda esta propiedad especial de los Arrays!
# Objetos
Los Arrays son buenos para listar, pero para otras tareas puede ser duro trabajar con ellos. Considera
nuestro array de amigos felinos. Qué pasa si quieres guardar más que nombres?
Esto puede ser frágil porque nuestro arrays cambian y agregamos un nuevo gato al comienzo podemos
también actualizar la variable posicionDeFelix apuntando a la nueva ubicación de la información de Felix
en los arreglos! Acá mostramos una forma más fácil de mantener guardada la información usando objetos:
var primerGato = { nombre: "felix", apellido: "el gato", dirección: "La calle" }
var segundoGato = { nombre: "sessa", lastName: "gato", direccion: "Liniers" }
var tercerGato = { nombre: "garfield", apellido: "gato", direccion: "Casa de John Bonachón" }
Por qué lo haríamos de esta manera? Porque ahora tenemos una variable para cada gato que podemos
usar a la hora de obtener valores del gato de una manera más conveniente y legible.
Puedes pensar a los Objetos como llaves de un llavero. Cada una es para una puerta en particular y si
tienes lindas etiquetas en tus llaves puedes abrir puertas muy rápidamente. De hecho, las cosas del lado
izquierdo del : son llamadas claves (también se conocen como propiedades) y las cosas del lado
derecho se llaman valores.
// un objeto con una sola clave llamada 'nombre' y un solo valor 'felix'
{ nombre: 'felix' }
Entonces por qué usar arrays si podemos poner toda nuestra información en objetos? Porque los objetos
no recuerdan el orden de las claves que seteas. puedes ingresar un objeto de esta manera:
O así!
Por lo tanto no puedes confiar en el orden de las claves de los objetos. Si querés hacer algo muy genial
puedes hacer un array lleno de objetos o un objeto de arrays!
var archivoDeAnimo = [
{
fecha: "20/10/2012",
estado: "aburrido"
},
{
fecha: "21/10/2012",
estado: "dormido"
},
{
fecha: "22/10/2012",
estado: "divertido"
}
]
Cuando combinas diferentes cosas como esta estás haciendo estructuras de datos, como legos!
# Callbacks
Los Callbacks no son realmente una característica de JavaScript como son los Objetos o los Arrays ,
sino una manera de usar funciones. Para entender por qué son útiles, primero tenemos que aprender
sobre programación asíncrona (también llamada async). El código asíncrono es por definición escrito de
una manera que no es síncrona. El código síncrono es fácil de entender y escribir. Este ejemplo lo ilustra:
Este pseudo-código síncrono descarga una foto adorable de un gato, sube la foto a twitter y genera un
tweet con la foto para @maxogden . Bastante simple!
(Nota del autor: Yo, @maxogden, acepto felizmente fotos de gatos por Twitter.)
Este código es síncrono porque para subir la foto al tweet, la descarga de la foto tiene que ser
completada. Esto significa que en la linea 2 no puede correr hasta que la tarea de la linea 1 esté
totalmente finalizada. Si fueramos a implementar este pseudo-código queremos estar seguros de que
descargar 'bloquea' la ejecución hasta que la descarga es finalizada, previniendo que cualquier otro
JavaScript sea ejecutado hasta que termine, así cuando la descarga se completa, se desbloquea la
ejecución de JavaScript y la linea 2 se ejecuta.
El código síncrono está bien para cosas que pasan rápido, pero es horrible para cosas que requieren
guardar, cargar o descargar. Que pasa si el servidor del que estás bajando la foto es lento, o la conexión a
internet que usas es lenta, o la computadora donde corres el código tiene muchas tabs con videos de
gatos en Youtube que anda lento? Significa que potencialmente puede tardar minutos esperando hasta
que la linea 2 se ejecute. Mientras tanto, como todo el JavaScript en la página está siendo bloqueado por
la descarga, la página va a congelarse totalmente, quedando sin respuesta hasta que la descarga finalice.
La ejecución bloqueante debe ser evitada a todo costo, especialmente cuando hace que tu programa se
congele o quede inusable. Asumamos que la foto de arriba toma 1 segundo para descargar. Para ilustrar
cuanto es un segundo para una computadora moderna, acá hay un programa que testea cuantas tareas
de JavaScript podemos procesar en un segundo.
function medirVelocidadCiclo() {
var contador = 0
function sumaUno() { contador = contador + 1 }
medirVelocidadCiclo()
Copia y pega el código de arriba en tu consola de JavaScript y luego de un segundo debería imprimir un
número. En mi computadora veo 8527360 , aproximadamente 8.5 millones. En un segundo JavaScript
puede llamar sumaUno 8.5 millones de veces! Entonces si tienes código síncrono descargando una foto, y
la foto tarda un segundo, significa que potencialmente estás previniendo la ejecución de 8.5 millones de
operaciones mientras JavaScript está bloqueado.
Algunos lenguajes tienen una función llamada sleep que bloquea la ejecución por un número de
segundos. Por ejemplo acá hay un código de bash corriendo Terminal.app en Mac OS que usa sleep .
Cuando corres el comando sleep 3 && echo 'me desperté' bloquea por 3 segundos antes de imprimir me
desperté .
JavaScript no tiene una función sleep . Como sos un gato, seguramente te estás preguntando, "Por qué
estoy aprendiendo un lenguaje de programación que no contempla dormir?". Pero no te vayas. En vez de
depender de sleep para esperar a que pasen cosas, el diseño de JavaScript alienta el uso de funciones
en su lugar. Si tienes que esperar que finalice la tarea A antes de comenzar la tarea B, pones todo el
código de la tarea B en una función y la llamas solo cuando A terminó.
a()
b()
Y este es no bloqueante:
a(b)
function a(fin) {
descargar('https://pbs.twimg.com/media/B4DDWBrCEAA8u4O.jpg:large', function finDescarga(error, png) {
// manejá el error si hay alguno
if (error) console.log('ups!', error)
Volvamos a nuestro ejemplo no-bloqueante, a(b) , donde llamamos a a y le pasamos b como primer
argumento. En la definición de la función a de arriba, el argumento fin es nuestra función b que le
pasamos. Este comportamiento es difícil de entender al principio. Cuando llamas una función, los
argumentos que pasas no van a tener necesariamente los mismos nombres de variable que cuando están
dentro de una función. En este caso lo que llamamos b es fin dentro de la función. Pero b y fin
son solo nombres de variables que apuntan a la misma función subyacente. Por lo general las funciones
callback son etiquetadas con nombres como fin o callback para dejar claro que esas funciones
deberían ser llamadas cuando la función actual termina su trabajo.
Entonces, mientras a haga su trabajo y llame a b cuando termine, ambas a y b son llamadas en sus
versiones bloqueantes y no-bloqueantes. La diferencia es que en la versión no-bloqueante no bloqueamos
la ejecución de JavaScript. En general el estilo no-bloqueante es donde escribes toda función para que
retorne lo más rápido posible, sin bloquear en ningún momento.
Para ir un poco más profundo: Si a toma un segundo para completar, y usas la versión bloqueante,
significa que puedes hacer una sola cosa. Si usas la versión no-bloqueante (usando callbacks) puedes
hascer literalmente millones de otras cosas en el mismo segundo, lo que significa que puedes terminar tu
trabajo millones de veces más rápido y dormir el resto del día.
Recordarlo: Programar se trata de ser vago y deberías ser vos el que duerma, y no tu computadora.
Con suerte puedes ver ahora como los callbacks son solo funciones que llaman a otras funciones luego de
una tarea asíncrona. Algunos ejemplos clásicos de tareas asíncronas son leer una foto, descargar una
canción, subir una foto, hablarle a la base de datos, esperar a que un usuario aprete una tecla o haga click
en un link, etc. Cualquier cosa toma tiempo. JavaScript es genial manejando tareas asíncronas como esas
siempre y cuando te tomes el tiempo de aprender como usar callbacks y mantener tu JavaScript lejos de
ser bloqueado.
Fin!
Este es solo el comienzo de tu relación con JavaScript! No puedes aprender todo de una, pero puedes
buscar que funciona para vos e intentar aprender todos los conceptos acá.
Te recomiendo que vuelvas mañana y lo hagas todo de nuevo desde el principio! Puede tomarte algunas
pasadas hasta que entiendas todo (programar es difícil). Solo intenta evitar leer esta página en cuartos
que contengan objetos brillantes... Pueden ser increiblemente distractivos.
Tienes algún otro tópico que quieres que sea cubierto? Abre un issue para ello en github.
# Lectura recomendada
JavaScript para Gatos se saltea un montón de detalles que no son importantes para empezar (los gatos
no son famosos por su atención), pero si sientes que necesitas aprender en profundidad mira esto:
Nota del traductor: La información de los siguientes links es en inglés. Lamentablemente escasea la
bibliografía en español. Tomalo como una buena excusa para aprender un nuevo lenguaje (además de
JavaScript)
NodeSchool.io es un software educacional open source manejado por la comunidad que enseña
diferentes areas de web development en un formato interactivo y auto-guiado. Yo ayudé a hacer
NodeSchool! lamentablemente este sitio tiene menos gatos.
Eloquent Javascript es un libro gratuito que te enseña JavaScript! Es muy bueno! Especialmente el
capítulo llamado values, variables, and control flow
La Guía de Mozilla de JavaScript también tiene un excelente capítulo llamado values, variables and
literals
La guía de estilo estándar` de JS es un "zero configuration" linter para el estilo de JavaScript que
yo uso.
# Clientes satisfechos
JSForCats.com es un trabajo en progreso con amor de @maxogden. Si quieres contribuir con este
material y mejorarlo, el repo de GitHub está por acá.
El traductor @impronunciable también es amigo de algunos gatos