Вы находитесь на странице: 1из 9

En términos generales y para fines del tutorial enmarcaremos el desarrollo orientado a objetos en 4 partes.

Los Objetos que son los componentes principales de nuestra aplicación y son los que hacen el trabajo, en JavaScript como sabemos
podemos usar objetos literales o funciones constructoras que creen objetos. Algo que es importante saber es que las funciones son
objetos en JavaScript.
Encapsulación este concepto engloba lo referido a que los objetos tienen un conjunto de atributos y métodos que hacen un trabajo
en específico y este trabajo es ajeno y oculto a los demás objetos de la aplicación lo que nos permite separar un conjunto específico
de funciones en diferentes objetos en la aplicación.

Herencia como el nombre lo dice se trata de obtener comportamientos y atributos de los objetos padres (clases en otros lenguajes de
POO, funciones en JavaScript).
Finalmente la instanciaque es una implementación del objeto dentro de nuestra aplicación, es un concepto un poco difícil de explicar
pero digamos que es una copia del objeto que creamos. Por ejemplo.

1. function Arbol (tipoDeArbol) {}


2. //Arbol es una funcion constructora por
3. //la que la invocaremos usando el keyword new
4.
5. var arbolBanana = new Arbol ("banana");
6. // arbolBanana es una instancia de Arbol

En el ejemplo Arbol es una función y un objeto (ya habíamos dicho que en JavaScript las funciones son Objetos) y arbolBanana es
una instancia de Arbol, esta instancia puede tener sus propios métodos y heredar los métodos y propiedades del objeto padre.

POO en JavaScript
Ya que hemos definido estos conceptos que son muy importantes podemos hablar concretamente de la programación en JavaScript.
Hay dos patrones de desarrollo importantes en la POO en javascript el primero se trata de la creación de objetos (Encapsulación) y el
segundo la reutilización de código (Herencia).

POO en JavaScript (Encapsulación)


La creación de objetos.

En JavaScript hay dos formas de crear objetos la primera es hacerlo mediante el patrón de creación literal, por ejemplo:

1. var objeto = {nombre: "Web Bizarro", url: "http://www.webbizarro.com"};

La otra forma es crear una función constructor, lo que conoceríamos como clases en otros lenguajes en JavaScript son funciones.

1. function Persona (nombre, profesion) {}


2. //Perosona() es la función constructora
3.
4. var richard = new Persona ("Richard", "Developer");
5. // richard es un objeto creado a partir dela función construtura

En el último ejemplo vemos que podemos crear una instancia del objeto a partir de una función constructora y luego podemos agregar
atributos o métodos a esas instancias. Hay muchas formas de crear objetos a partir de funciones constructoras y a partir de ahora
cuando nos refiramos a creación de objetos en el tutorial estaremos hablando de este método.
Encapsulación
Ya hemos aprendido que la encapsulación se trata de colocar todo dentro de los objetos. En JavaScript el concepto de encapsulación se
logra combinando las funciones constructoras junto con el patrón de prototype y esta es la mejor forma de conseguir lo que estamos
buscando que es colocar los métodos y atributos de un objeto dentro de si mismo.
Ahora veamos un ejemplo que iremos explicado poco a poco. Vamos a crear una pequeña aplicación donde tendremos usuarios que
tendrán un puntaje en un examen.

1. var Usuario = function(nombre, email){


2. this.nombre = nombre;
3. this.email = email;
4. this.puntos = [];
5. };

Aquí definimos las propiedades del usuario en una función constructora como lo habíamos visto anteriormente.

1. Usuario.prototype = {
2. constructor: Usuario,
3. salvarPuntos: function (puntos) {
4. this.puntos.push(puntos);
5. },
6. mostrarNombrePuntos: function () {
7. var todosPuntos = this.puntos.length > 0 ? this.puntos.join(",") : "No hay puntos aun";
8. return this.nombre + todosPuntos;
9. },
10. cambiarEmail: function (newEmail) {
11. this.email = newEmail;
12. }
13. };

Aquí lo que hacemos es modificar la propiedad prototype con un objeto literal esto nos permitirá crear todos nuestros métodos en el
objeto y en un futuro heredar estas propiedades a otros objetos. Esta forma es muy cómoda de usar ya que escribimos todo el
comportamiento del objeto de una vez, aunque también podemos hacerlo de uno en uno de esta forma.

1. Usuario.prototype.constructor = Usuario;
2. Usuario.prototype.salvarPuntos = function (puntos) {
3. this.puntos.push(puntos);
4. };

Sobrescribir el prototype con un objeto literal permite ver la encapsulación del objeto de una mejor forma y por otro lado es mucho
menos código el que tenemos que escribir.
Algo importante que debemos decir es que usamos prototype porque queremos que las instancias que creemos de este objeto hereden
los atributos y métodos del mismo. Otra cosa que debes tomar en cuenta es la línea donde colocamos constructor, esta se usa para
sobrescribir el método constructor del objeto lo que quiere decir que esa línea tienes que incluirla y esta una de las desventajas de
sobrescribir prototype con un objeto literal ya que la función constructora por default desaparece y tenemos que colocarla
manualmente.
1. var usuario1 = new Usuario("Alvaro", "alvaro@ejemplo.com");
2. usuario1. cambiarEmail("alvaro2@ejemplo.com");
3. usuario1.salvarPuntos(10);
4. usuario1.salvarPuntos(15);
5. usuario1.mostrarNombrePuntos(); // alvaro 10,15
6.
7. var usuario2 = new Usuario("Gianfranco", "gianfranco@ejemplo.com");
8. usuario2.salvarPuntos(12);
9. usuario2.salvarPuntos(17);
10. usuario2.mostrarNombrePuntos(); // Gianfranco 12,17

Como vemos cada objeto es independiente y encapsula sus metodos y propiedades lo que lo hace independiente de los otros. Mediante
este metodo puedes usar operadores standar para los objetos incluyendo instanceOf y for-in mediante la propiedad hasOwnProperty.

Esta es la última parte de nuestro tutorial de POO en JavaScript en el cual hablaremos sobre herencia, y este es uno de los conceptos
que pueden causar un poco de confusión en JavaScript. En otros lenguajes tenemos las clases y para heredar solo tenemos que colocar
extends o algo parecido, pero el lenguaje JavaScript no nos permite hacer esto por lo que debemos buscar otros métodos para construir
el concepto de herencia y hay muchas formas de hacerlo, nosotros nos concentraremos en una, Parasitic Combination Inheritance o
herencia por combinación parasitaria, y si se que suena un poco raro pero ya iremos viendo de que se trata.
Anteriormente creamos un objeto usuario que almacenaba sus datos y las notas que obtenía en un examen ahora implementaremos
la herencia creando una pequeña aplicación de examen.

Pero porque debemos usar herencia en JavaScript, la respuesta es sencilla menos trabajo, si hacemos código reutilizable podemos
aprovechar la herencia para no tener que repetirlo y evitar la fatiga como diría el doctor Chapatin.

Primero vamos a revisar un modelo de creación de objetos basado en lo que ya vimos anteriormente, este método fue creado por
Douglas Crockford.

1. if (typeof Object.create !== 'function') {


2. Object.create = function (o) {
3. function F() {
4. }
5.
6. F.prototype = o;
7. return new F();
8. };
9. }

El método Object.create fue implementado en la definición de EMACScrip5 y puedes usar simplemente Object.create(). Pero vamos
a ver que es lo que hace.

1. Object.create = function (o) {


2. // Crea una funcion temporal
3. function F() {
4. }
5.
6. // Sobrescribe el prototype de la funcion F por
7. // el objeto que recibe como parametro por lo que
8. // F ahora hereda todas las propiedades de el objeto o
9. F.prototype = o;
10.
11. // Por ultímo retornamos una instancia del objeto F(), esta
12. // instancia hereda los métodos y propiedades del objeto o pasado
13. // como parámetro, o podemos decir que es una copia de él.
14. return new F();
15. };

Es importante que entendamos bien esto por lo que veamos un pequeño ejemplo.

1. var carros = {
2. tipo: "sedan",
3. ruedas: 4
4. };
5.
6. var toyota = Object.create (carros);
7. //Como vemos el objeto toyota hereda todos los atributos del objeto carros.
8.
9. console.log(toyota.tipo); // sedan

Muy bien ahora que entendemos esto podemos pasar al siguiente punto la Parasitic Combination Inheritance para eso debemos
implementar una función que nos permitirá crear la herencia y que explicaremos a continuación.

1. function inheritPrototype(hijo, padre) {


2. // como discutimos antes el método de Crockford nos permite copiar
3. // copia las propiedades y metodos de unobjeto en otro por lo que
4. // copiaPadre es una copia de padre
5. var copiaPadre = Object.create(padre.prototype);
6.
7. // entonces debemos apuntar el constructor de la copia al hijo ya que
8. // como vimos antes el constructor de la copia desaparece y debemos
9. // sobreescribirlo para asegurarnos que apunte a la función correcta.
10. copiaPadre.constructor = hijo;
11.
12. // Finalmente sobrescribimos el prototype del hijo con la copia del padre
13. // de esta forma el hijo hereda todas las propiedades del objeto padre
14. hijo.prototype = copiaPadre;
15. }

Es muy importante entender esta función anterior ya que en esta se basa todo el asunto de la herencia en ella lo que hacemos es que el
hijo herede todas las propiedades y atributos del padre pero usando la copia como un intermediario.
Vamos a ver un ejemplo para poder ver todo esto funcionando en pleno.
Decíamos que haríamos un examen y los exámenes tienen preguntas por lo que crearemos preguntas de diferentes tipos. Primero
creamos la función padre

1. var Pregunta = function ( laPregunta, lasOpciones, laRespuesta){


2. this.pregunta = laPregunta;
3. this.opciones = lasOpciones;
4. this.respuesta = laRespuesta;
5. this.respuestaUsuario = "";
6. // veamos como crear variables privadas que no puedes ser accedidas mediante la instancia
7. var fecha = new Date();
8.
9. // Tambien podemos crear constantes disponibles para todas las instancias mediante metodos
10. // publicos que accedan a las variables privadas
11. var FECHA_DE_CREACION = fecha.toLocaleDateString();
12.
13. // Debemos crear una método para acceder a la variable FECHA_DE_CREACION que sea
14. // publico, esta es una forma de definir privilegios de acceso a los atributos.
15. this.getFechaCreacion = function () {
16. return FECHA_DE_CREACION;
17. };
18. };

Ahora podremos modificar el Prototype del objeto padre para agregar algunos comportamientos a la clase como obtener la respuesta
correcta y mostrar las opciones.

1. Pregunta.prototype.getRespuestaCorrecta = function() {
2. return this.respuesta;
3. };
4.
5. Pregunta.prototype.getRespuestadelUsuario = function() {
6. return this.respuestaUsuario;
7. };
8.
9. Pregunta.prototype.mostrarOpciones = function() {
10. var preguntaMostrar = "<div class='pregunta'>" + this.pregunta + "</div><ul>";
11. contador = 0;
12. this.opciones.forEach(function (opcion) {
13. preguntaMostrar += '<li><input type="radio" name="opcion" value="' + contador + '">' + opcion + '</li>';
14. contador++;
15. });
16. preguntaMostrar += "</ul>";
17. console.log (preguntaMostrar);
18. };

Ahora que tenemos lista la“Super clase” podemos dedicarnos a crear “Sub clases” a partir de ellas.
Preguntas con múltiples opciones

1. var SeleccionMultiple = function (laPregunta, lasOpciones, laRespuesta) {


2. // Lo que haremos en esta parte sera hacer que la clase seleccion multiple llame al
3. // método constructor de la clase pregunta mediante call y pasaremos como parametro
4. // el mismo objeto SeleccionMultiple mediante this
5.
6. Pregunta.call(this, laPregunta, lasOpciones, laRespuesta);
7. };

Luego usaremos el método que definimos anteriormente para aplicar el patrón de Parasitic Combination Inheritance a nuestra
aplicación.

1. inheritPrototype(SeleccionMultiple, Pregunta);

Después de esto todos los atributos y metidos del padre pasaran al hijo y podremos agregar nuevos métodos al hijo. Tienes que tener
cuidado en este punto los métodos al hijo deben agregarse luego de hacer la herencia del padre sino serán sobrescritos al modificar el
prototype.
Por último veamos algo muy necesario en la POO que es sobrescribir métodos, por que no todos los hijos hacen las cosas como sus
padres.

Preguntas Drag and drop

1. var DragandDrop = function (laPregunta, lasOpciones, laRespuesta) {


2. Pregunta.call(this, laPregunta, lasOpciones, laRespuesta);
3. }
4.
5. inheritPrototype(DragandDrop, Pregunta);

Para modificar un metodo solo debemos modificar el prototype del objeto luego de la herencia.

1. DragandDrop.prototype.mostrarOpciones = function () {
2. console.log(this.pregunta);
3. };

De esta forma las preguntas de selección múltiple mostrarán un div con la pregunta y radio buttons con las opciones en cambio
las preguntas de Drag and Drop solo mostrarán un texto con la pregunta.
Hay muchas formas de realizar herencia incluso librerías que lo hacen mucho más sencillo pero lo importante es que entiendas los
conceptos básicos de como funcionan estas librerías, además esta es una de las formas más optimizadas para realizar herencia en
JavaScript.
------------------------------
Síncrona vs Asíncrona

Programación Paralela
Acciones Bloqueantes
Paralelismo: varios objetos realizando una acción cada uno simultáneamente (síncrono)

Programación Concurrente
Acciones NO Bloqueantes
Concurrencia: un solo objeto, con varias tareas “activas” entre las que va alternando(asíncrono)
------------------------------

Síncrona vs Asíncrona (Abriendo un Archivo)

Bloqueante
1. Abrir el archivo
2. Leer el archivo
3. Imprimir contenido
4. Hacer algo más
No Bloqueante
 Abrir el archivo
 Leer el archivo
 Cuando termines,
 Imprimir contenido
 Hacer algo más

Elevación (Hoisting)
En ejecución, todas las declaraciones var y function son movidas al comienzo de cada función.
Es buena práctica declarar todas las variables juntas en la primera línea, con el fín de evitar falsas expectativas.
Desde ES6 con let podemos tener variables de bloque y evitar la elevación, por ello ya no deberías usar var.

Modo Estrícto (Strict Mode)


El modo estricto en ES5 es una manera de optar por una forma restringida de JavaScript. El código en modo estricto y en modo no
estrícto pueden coexistir. Desde ES6 ya no es necesario.

Funciones Anónimas(Anonymous Functions)


Son declaradas dinámicamente en tiempo de ejecución. Son llamadas anónimas porque no poseen un nombre de la misma manera que
las funciones normales.
Desde ES6 tenemos las funciones flechas
() => { ... }
Funciones de Clausura (Closure Functions)
Son un patrón de diseño muy utilizado en JavaScript que nos permite mantener privacidad en atributos y métodos. Encapsulan
variables y funciones que únicamente serán accesibles si son devueltas con el operador return.

Funciones Auto Invocadas(Immediately-Invoked Functions)


Es un patrón de diseño que produce un scope léxico. Usadas para evitar hoisting, protege el código del ambiente global y
simultáneamente permite acceder a los métodos publicos al tiempo que conserva la privacidad en las variables definidas dentro.
Tipos de Datos
1. Primitivos (se accede directamente al valor)
string
number
boolean
null
undefined
2. Complejos (se accede a la referencia del valor)
object = {}
array = []
function () { }

Características de la POO
 Abstracción: Aislación de un elemento de su contexto. Define las características esenciales de un objeto.
 Encapsulamiento: Reúne al mismo nivel de abstracción, a todos los elementos pertenecientes a una misma entidad.
 Modularidad: Permite dividir una aplicación en varias partes más pequeñas, independientes unas de otras.
 Ocultación: Los objetos están aislados del exterior, protegiendo a sus propiedades para no ser modificadas por
aquellos que no tengan derecho a acceder a las mismas.
 Polimorfismo: Capacidad que da a diferentes objetos, la posibilidad de contar con métodos y atributos de igual
nombre, sin que los de un objeto interfieran con los del otro.
 Herancia: Es la relación existente entre dos o más clases, donde una es la principal (madre) y otras son secundarias y
dependen (heredan) de ellas (clases hijas), donde a la vez, los objetos heredan las características de los objetos de los
cuales dependen.

Entendiendo this en JavaScript


this en JavaScript tiene un comportamiento muy diferente a otros lenguajes de programación, incluso para algunos desarrolladores es
considerado uno de los grandes errores de diseño del lenguaje.
La clave para entender el comportamiento de this, es tener claro donde se invoca, para saber qué objeto le asigna.
 Asignación implícita
 Asignación explícita
 Asignación con new
 Asignación global
 Las Arrow Functions

Programación basada en Clases


ES6 aporta un 'azúcar sintáctico' para declarar una clase como en la mayoría de los lenguajes POO, pero por debajo sigue siendo una
función prototipal.
Control de flujo asíncrono
 Callbacks
 Promesas
 Generadores
 Funciones Asíncronas (async y await)

Вам также может понравиться