¡Al grano, JavaScript!

JavaScript es un lenguaje de objetos. Como todo lenguaje, tiene sus particularidades, sí, pero si tenés claros los conceptos de la programación con objetos, aprenderlo es trivial. ¿No me creés? Acá va un mini tutorial que lo demuestra.

Cuando uno transita la jungla de los lenguajes, muchas veces es fácil perderse en los aspectos sintácticos. Sin embargo, estos en lo absoluto son los más importantes. Por eso, para poder encontrar nuevamente el camino, necesitaremos siempre diferenciar lo valioso de lo superficial.
Las toneladas de tutoriales en Internet que empiezan por explicar cómo escribir el for, 35,3 formas de acceder sus properties o las reglas sobre cuando el punto y coman es opcional, lejos de ser brújulas, son distracciones.

Los objetos

Si JavaScript es un verdadero lenguaje de objetos (¡y no de clases!), lo más simple debe ser crear un objeto. ¿Y saben algo? ¡Lo es!

Esto define un objeto vacío, que no entiende (casi) ningún mensaje

Las variables

A los objetos podemos referenciarlos. Para ello tenemos variables.

Sí hubiera dudas: sí, una variable se declara con var y se asigna con = .

Los slots

Los objetos en JavaScript son colecciones de slots: un "lugar" con nombre en el que se puede referenciar a otro objeto. En cualquier momento podemos agregar slots, como por ejemplo ubicacion:

Por si no lo notaste, las sentencias (ya sean asignaciones de slots o variables) se separan con ;.

Los métodos

En los slots podemos meter cualquier cosa, incluidos también números, strings y booleanos. Y también podemos meter otro tipo de objeto: bloques de código (JavaScript los llama functions). Por ejemplo:

Moraleja: así tenemos métodos.

Y el this, como se observa, se comporta en este caso como la referencia al objeto receptor del mensaje, como en cualquier lenguaje de objetos convencional.

Los mensajes

Con esto podemos enviar mensajes:

Los parámetros del mensaje van entre paréntesis, separados por coma.

Números, Booleanos, Strings

En JavaScript también contamos con números, booleanos, strings, con mayormente la misma sintaxis de Java/C/C#:

De paso se ve que

  1. los comentarios se escriben con doble barra como en C/Java/C++/C#, etc
  2. las functions pueden tener retorno

Ah, algo importante: la única excepción a los operadores estilo C es la comparación, que se escribe ===. Si comparamos números y strings, compara por equivalencia (es decir, que tengan el mismo valor). Si comparamos cualquier otra cosa, compara por identidad (es decir, que sea el mismo objeto).

Polimorfismo

El polimorfismo es casi gratuito: basta con que dos objetos entiendan el mismo mensaje de forma similar. Ejemplo:

Esto le envía el mensaje volar() a superman y a pepita sin importarle como lo entiende cada uno.

Y de paso, notamos que:

  1. En JavaScript tenemos listas, que las escribimos con corchetes, y separando sus elementos con comas. En JavaScript les dicen arrays
  2. Los arrays entienden mensajes básicos de colecciones como forEach, map, filter, etc.

Prototipos

¿Cómo hago para crear varios objetos parecidos? ¡Clonándolo!

Esto crea un objeto complemente nuevo, que tiene a pepita como prototipo. Si accedemos a un slot al objeto rigoberta, y éste no lo tiene correspondiente, lo buscará en su prototipo. Y como vimos, los métodos y el envío de mensajes son sólo casos particulares de slots y acceso a slots.

Por tanto, en este caso, tanto anastasia, como rigoberta y pepita entienden los mismos mensajes y se comportan igual.

Es importante notar que los clones son objetos diferentes, podemos modificarles sus slots y pepita no se ve afectada.

De todas formas: ojo. Dado que rigoberta tiene como prototipo a pepita y no le asignamos energia propia, si energia de pepita cambia, energia de rigoberta también cambiará. Esto no es un bug de JavaScript, pero hay que tenerlo en cuenta porque capaz no es lo que queremos.

Objetos literales

Hay un pequeño atajo que se usa bastante para crear objetos simples. En lugar de crear un objeto vacío y asignarme slots uno a uno, se puede hacer todo en un sólo paso.

Esto es equivalente a crear un objeto vacío, y asignarle energia, volar y puedeVolar. Creo que la sintaxis es bastante evidente, pero por las dudas:

  • Se separa el nombre del slot y su valor con :
  • Se separa un slot de otro con ,

Constructores

Y para cerrar, a veces pasa que en lugar de crear un objeto concreto y listo para usar, y clonarlo varias veces, nos es mas fácil pensar en un objeto que represente el molde de varios parecidos.

Por ejemplo, en lugar de crear a pepita y clonarla, podríamos crear un objeto que represente el concepto abstracto de Golondrina (sí, pepita y sus amigas son golondrinas, ¿no era obvio?)

Y eso se vería así:

¿Qué tiene de bueno esto? En este caso, si venimos acostumbrado a las clases, es más fácil de razonar, porque separamos el estado del comportamiento, tal como en la definición de una clase.

Y no caemos en el extraño caso (insisto, extraño si estamos acostumbrados a las clases) que contábamos antes; ahora no hay forma de accidentalmente utilizar la energía de pepita desde rigoberta.

Como esto es bastante común, tenemos una última sintaxis particular que condensa la declaración de un objeto destinado sólo a ser prototipo y un constructor para las instancias de este prototipo.

Por si te agarró distraído:

  • El constructor es una function que inicializa al objeto (this)
  • La function la aplicamos con el operador new para crear al objeto e inicializarlo en un sólo paso
  • El prototipo que usamos para crear al objeto lo sacamos del slot prototype de la function (sí, como las functions son objetos, podemos asignarle y acceder sus slots)

Lo importante es que ya podés modelar usando todo el poder del paradigma de objetos.

¿Y la herencia? ¿Y los mixins? ¿Y candela?

No hay. Fin de la historia. JavaScript es un lenguaje orientado a objetos. Se resuelve todo utilizando composición, delegación, polimorfismo y prototipos.

¿Y null?

OK, existe null. Pero un buen diseño no necesita nulls. No lo uses salvo que la tecnología que estés usando te fuerce a ello.

Che, el this no me anda

Pucha, te diste cuenta. Hay una situación concreta en la que el this no es quien debería (locuras de JavaScript): cuando lo usás dentro de un bloque de código. Ejemplo:

¿Que se hace en ese caso? Los bloques entienden el mensaje bind, que deja claro quien es this dentro del bloque:

Moraleja: siempre que pasemos un bloque de código en un método, tenemos que tener cuidado con el this.

Un poco de sinceridad

En realidad nada es tan fácil, particularmente en JavaScript.

Recién hice muchas concesiones y simplificaciones para poder ir a lo importante y poder salir programando. La mas notable es que en EcmaScript 6 (la especificación en la que se basa JavaScript) sí hay soporte nativo para clases. Otra es que no mostramos el clásico var self = this; Y así hay muchas más.

Pero no son simplificaciones caprichosas: el modelo de programación que acá presento de JavaScript es suficiente para programar con objetos, y además es consistente en la mayoría de los casos. Digo en la mayoría, porque toda abstracción, tarde o temprano, gotea:

Otra concesión que hice fue valerme de la terminología de objetos proveniente del lado de Ruby, Smalltalk y Self. No por purista o porque sea mejor, sino por la simpleza de pensar en términos de objetos, mensaje y slots.

Finalmente, si querés profundizar, hay cientos de libros escritos sobre JavaScript. Por ejemplo:

¡Hasta la próxima!