1. Programación orientada a objetos (OOP) con JavascriptClases vs prototipos JS es basado en prototípos. Un prototípo es un objeto abstracto, capaz de contener otros objetos dentro, los cuales pueden ser distintos tipos de datos: variables (numeros, cadenas de texto, valores lógicos), vectores, funciones e inclusive otros grupos de objetos. Entonces, en vez de programar una clase, para estar orientados a objetos en JS definimos un prototípo. Las variables dentro de este serán las propiedades, y las funciones serán los métodos: [Objeto = Prototípo]{ [ Propiedad = Variable ] [ Método = Funcion ] }
2. Creación del objeto La creación de un objeto se hace con una función, que será la constructora, y a la vez la que identifique el objeto. Hay dos formas de definir la función constructora: Definir una función o definir una variable cuyo contenido sea una función. Puede parecer redundante, lo es. Veamos ambas formas: Definir una función functionGato( parametros ) { // Codigo }; Definir una variable cuyo contenido sea una función. var Gato = function (parametros) { /* Codigo*/ }
3. Propiedades del objeto Las propiedades del objeto se definen en forma de variables. Estas variables deben estar situadas dentro de la función constructora, marcadas con "this", para poder ser accesadas como parte del objeto. Las variables reciben parámetros que se envían al crear una nueva instancia del objeto. Por ejemplo: var Gato = function (nombre, color, edad) { this.nombre = nombre; this.color = color; this.edad = edad; } Usando un objeto vamos a crear un gato nuevo, y a asignarle las propiedades: var Michi = new Gato("Michifu", "azul", 2); Si queremos comprobar alguna de las propiedades de nuestro objeto lo haríamos así: Variable_que_define_el_objeto (punto) propiedad_deseada. Por lo tanto: alert("El gato es de color "+Michi.color); Lo que nos da el resultado: "El gato es de color azul";
4. Métodos Un método es una función dentro del objeto. Hay varios formas de crear un método nuevo: Extendiendo el prototipo, creando una variable tipo función, o vinculando una función externa al objeto. Método 1: Vinculación externa Con este método declaramos que una de las propiedades, llamará a una función externa: [...] this.comer = comerExterna; [...] functioncomerExterna() { alert("El gato "+this.nombre+" se comió un ratón"); } [...] Michi.comer(); [ Salida = "El gato Michifu se comió un ratón" ] Método 2: Extensión del prototipo Como los objetos están compuestos por prototipos en JavaScript, nosotros podemos aumentarle métodos al prototipo del objeto directamente, de la siguiente manera: //[ No tocamos la funcion constructora ] Gato.prototype.comer = function() { alert("El gato "+this.nombre+" se comió un ratón"); } //[...] Michi.comer(); //[ Salida = "El gato Michifu se comió un ratón" ]
5. Método 3: Definición en la función constructora Con este método, asignamos una propiedad como función dentro de la constructora: //[...] this.comer = function() { alert("El gato "+this.nombre+" se comió un ratón"); } //[...] Michi.comer(); //[ Salida = "El gato Michifu se comió un ratón" ] Nótese que en los tres métodos, es posible pasar parámetros a la función de la manera normal en que cualquier función trabaja. Además, en cualquiera de los métodos, this se refiere al objeto (en este caso Gato).
6. Herencia La herencia de métodos / propiedades. En JavaScript lo podemos lograr mediante los prototipos. Ahora, crearemos una raza de gato, la raza Siamés. Entonces creemos dos constructoras apartes para cada una, y hagamos que siamés herede de gato: var Gato = function () { this.ojos = 2; this.piernas = 4;} varSiames = function () { this.color = "blanco"; this.color_ojos = "azul"; } //Como vemos, ambos tienen propiedades distintas. Ahora, heredemos: Siames.prototype = new Gato(); //Eso hace que se copie el prototipo de Gato y se añada al de Siames. Probemos : varCatboy = new Siames(); alert(Catboy.ojos); //Retorna 2! ^_^ alert(Catboy.color); //Retorna "blanco", asi que conserva sus propiedades
7. Métodos y propiedades privadas Los métodos y funciones eran totalmente públicos: Modificables y legibles desde cualquier parte. Como "privatizar" variables: var Gato = function (nombre) { this.nombre = nombre; //Creamos una variable privada sin asignarle "this" a esta: var frecuencia = "moderada"; // Creamos un método privado en muchos aspectos definiendo una función normal function irAlBanio(frecuencia) { alert("El gato va al baño con frecuencia "+frecuencia); } irAlBano(frecuencia); } var Michin = new Gato("Michifu"); El código anterior crea la variable privada "frecuencia", y la función privada "irAlBanio". Para comprobar que la variable sea privada ejecutemos : alert(Michin.frecuencia), lo que devuelve: undefined
8. Sin embargo, aun podemos usar esas variables o funciones tanto en la función constructora, simplemente son funciones que nos permiten leer las propiedades: var Gato = function (nombre) { this.nombre = nombre; //Creamos una variable privada sin asignarle "this" a esta: var frecuencia = "moderada"; // Creamos un método privado en muchos aspectos definiendo una funcion normal: function irAlBano(frecuencia) { alert("El gato va al baño con frecuencia "+frecuencia); } //Es aquí donde accedo a mi propiedad privada: this.leerFrec = function() { irAlBano(frecuencia); } } var Michin = new Gato("Michifu"); Michin.leerFrec(); //Nos retorna "El gato va al baño con frecuencia moderada" ;)
9. Extensión de objetos nativos mediante el prototipo Como todos los objetos de JavaScript tienen prototipo, podemos añadir utilidades a nuestros objetos de siempre. Por ejemplo añadiendo una función a Array: Array.prototype.coincidencias = function(palabra){ //array es nuestra nueva propiedad, que le añadimos a nuestra función coincidencias coincidencias = 0; for (i=0; i<this.length; i++) { if (this[i] == palabra){ coincidencias++; } } alert("Se encontraron "+coincidencias+" coincidencia(s) de la palabra"); } // Podemos usar el array siguiente, (inicializamos con una lista inicializadora): clabbers = Array("Freddie", "Mx", "Neo_JP", "Zarzamora", "Ramm", "Fael"); // O este: clabbers = Array("Freddie", "Mx", "Neo_JP", "Zarzamora", "Mx", "Mx"); //Y luego: clabbers.coincidencias("Mx"); //Entonces la función nos notificará cuantas veces esta una palabra en un array.