Ruby (Rails), Java, JavaScript, PostgreSQL, Cloud, Ubuntu :)

Entendiendo la Orientación a Objetos en Javascript

Javascript Objects
Si eres desarrollador web, con seguridad usas javascript con frecuencia. Es probable que ya sepas como crear y usar objetos, pero no te sientes cómodo al hacerlo, después de todo Javascript no se asemeja mucho a algunos de los lenguajes "puramente" orientados a objetos. Pero, con un poco de ayuda es posible que puedas comprender lo que realmente significa orientación a objetos en Javascript.

¿Qué es un objeto en Javascript

En términos de Javascript, un objeto es una colección de pares key-value (llave / valor), dónde la llave (key) debe ser una cadena. El valor no tiene ningún tipo de restricciones, por tanto puede almacenar primitivas, objetos y funciones (en ese contexto se les llama "mètodos"). Las variables y los campos del objeto solo referencia al objeto. Los objetos pueden ser comparados solo en terminos de identidad referencial.

¿Cómo crear un objeto en Javascript?

Hay muchas maneras de crear un objeto en Javascript, dejame nombrar algunas de éstas.

Objeto Literal

var perro = {
  name: "Oso",
  ladrar: function() {
  console.log("wau, wau")
  }
}
Lo cual crea explicitamente el objeto perro con el campo nombre y el método ladrar. El concepto básico aquí es que muchas veces en tu aplicación hay necesidad de tener muchos objetos con la misma estructura y comportamiento. La orientación a objetos se revela en las instancias, no en las clases.

Método Object Create

var gato = Object.create
  gato.nombre = "Misifú"
  gato.miau = function() {
  console.log("miau miau")
}
Object.create instancia un objeto gato vacío -sin ningún campo, convirtiéndose en un prototipo del objeto creado. Más adelante abordaremos los prototipos, mientras enfoquémonos en el objeto gato. Agregamos algunos atributos y comportamiento por medio de la asignación de valores y funciones a sus campos inicialmente no existentes. Por supuesto en tiempo real puedes cambiar ambos campos con nuevos valores (o funciones) e incluso remover algún campo.

Función constructor

function Leon(nombre) {
this.nombre = nombre;
this.rugir = function() {
console.log(" arrr arrr")
}
}
var leon = new Leon("Tonio")
Primero que todo qué es Leon? Como puedes ver es una función, pero un tipo especial, es llamado constructor, ya que construye nuevos objetos con determinados atributos y comportamiento. Ojo, en este ejemplo cada objeto construido con Leon tendrá un método rugir distinto. Más adelante veremos como compartir métodos.
Esta es la primera manera de diferenciar las clases de los objetos - si creaste un objeto con un constructor puedes decir, que el objeto es su instancia-.
leon instaceof Leon //= true
Pero recuerda - leon no es una instancia de la clase Leon, sino que leon es una instanciada por el constructor Leon.

Herencia por prototipos

En javascript la herencia se basa en objetos, así que un objeto "a" puede heredar atributos y comportamiento de un objeto "b", entonces el objeto "b" es llamado prototipo del objeto "a". Por supuesto "b" puede también puede tener prototipo, entonces cada objeto tiene una cadena de prototipos. Veamos un ejemplo:
var protoGato = {
nombre: "Misifu",
miagar: function() {
return this.nombre + ": miau miau"
}
}
// 1
var gato = Object.create(protoGato)
console.log(gato.nombre) // Misifu
console.log(gato.miagar()) // Misifu: miau miau

//2
protoGato.nombre = "Proto"
console.log(gato.nombre) // Proto
console.log(gato.miagar()) // Proto: miau miau

// 3
gato.nombre = "Nyan Cat"
console.log(gato.nombre) // Nyan Cat
console.log(protoGato.nombre) // Proto
console.log(gato.miagar()) // Nyan Cat: miau miau

//4
gato.miagar = function() {
return this.nombre + ": rrruf rrruf"
}
console.log(gato.miagar()) // Nyan Cat: rrruf rrruf
console.log(protoCat.miagar()) //Proto: miau miau
Como puedes ver en este ejemplo los campos de protoGato son reservados, si gato no tiene manera de interpretar un campo lo busca en el prototipo, y luego de forma recursiva en el prototipo del prototipo... Si ese campo es una función se pasa también el objeto correcto - en el cual el método es invocado - como tal. Y si el método encontrado usa un campo de un objeto el interprete comienza buscando desde el objeto original.
Por tanto un prototipo define por defecto los atributos y comportamiento de los objetos que heredan de éste y esa es la manera de compartir y rehusar comportamientos comunes. La gran diferencia acá es que no heredas de claces instanciadas, sino que solo instancias, de manera que si cambias un atributo de un prototipo en tiempo real, todos los objetos que heredan de éste serán afectados a menos que estos sobrescriban el atributo.

Prototipo común para objectos construidos

Hemos visto como crear objetos con prototipo con Objetc.create. También puedes asignar un prototipo común para objetos creados por constructor:
vas animal = {
ladrar: function() {
return this.nombre + ": wau wau"
}
}

function Lobo(nombre) {
this.nombre = nombre
}

Lobo.prototype = animal

var lobo = new Lobo("Tyson")
console.log(lobo.ladrar()) // Tyson: wau wau
Lobo.prototype = animal significa que quieres que cada objeto construido tenga un animal como prototipo. Por supuesto que el prototipo puede ser también creado con un constructor.
function Animal() {
//...
}

function Lobo() {
//...
}

Lobo.prototype = new Animal()
var lobo = new Lobo()
En este caso el objeto lobo is tanto instancia de Lobo como de Animal en terminos del operador instanceof. ¿Por qué lobo lobo intanceof Animal es verdadero? Supongamos que eliminamos todos los atributos correspondientes a Lobo, como se va a comportar lobo? como Animal, por supuesto, entonces esa es la respuesta.