Micael Gallego2014-01-24T03:48:48-08:00http://micaelgallego.github.comMicael GallegoCurso de desarrollo web (Sesión 2 y 3)2014-01-23T00:00:00-08:00http://micaelgallego.github.com/blog/Curso-de-desarrollo-web-sesiones-2-y-3<p>En este post seguimos con las sesiones de la asignatura de desarrollo web del grado en ingeniería de computadores. En concreto, publico la sesión 2 y la 3.</p>
<p>Sesión 2</p>
<iframe width="480" height="360" src="//www.youtube.com/embed/4Cfh2pODXok" frameborder="0" allowfullscreen></iframe>
<p><br/></p>
<p>Sesión 3</p>
<iframe width="480" height="360" src="//www.youtube.com/embed/7YUB_DUiJyU" frameborder="0" allowfullscreen></iframe>
<p><br/></p>
<p>Presentación del Tema 2</p>
<iframe src="http://www.slideshare.net/slideshow/embed_code/30337751" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>
<p> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/micaelgallego/tema2-tecnologas-de-desarrollo-de-aplicaciones-web" title="Tema2: Tecnologías de desarrollo web (Desarrollo Aplicaciones Web)" target="_blank">Tema2: Tecnologías de desarrollo web (Desarrollo Aplicaciones Web)</a> </strong> from <strong><a href="http://www.slideshare.net/micaelgallego" target="_blank">Micael Gallego Carrillo</a></strong> </div></p>
Curso de desarrollo web (Sesión 1)2014-01-14T00:00:00-08:00http://micaelgallego.github.com/blog/Curso-de-desarrollo-web<p>Como muchos de vosotros ya sabéis, soy profesor de programación en la Universidad Rey Juan Carlos. Siempre me ha gustado aprender cosas y enseñar a los demás lo que había aprendido. Cuando hice la carrera, la mejor forma de estudiar era explicar a mis compañeros lo que tenía que aprender. Era como un reto, no sólo lo tienes que entender, además tienes que saber explicárselo a otro. Si no eres capaz de explicar algo, es que no lo entiendes.</p>
<p>Este cuatrimestre empiezo a impartir una asignatura de "Desarrollo de aplicaciones Web" en el "Grado en Ingeniería del Software". Y me gustaría compartir con vosotros el desarrollo del curso.</p>
<p>Intentaré ir publicando el material según lo vaya viendo en clase. El curso son aproximadamente 12 semanas, 4 horas de clase por semana. Algunas sesiones serán más teóricas y otras más prácticas.</p>
<p>Tengo pensado publicar las transparencias (en PDF y SlideShare) y un vídeo grabando mi portátil. Quizás haya por ahí otro software que permita hacer esto de forma más eficiente, pero es la única forma que se me ocurre de sincronizar la voz con las transparencias. Además, si consulto la web para ampliar información o abro el entorno de desarrollo para programar algo, se graba todo directamente. Había pensado en grabarme en vídeo según imparto las clases, pero a nivel logístico es bastante más complicado. Las clases son grandes y me suelo mover bastante, así que haría falta que alguien me grabara. Además, tampoco creo que aporte mucho valor verme el careto ;) (suficiente vergüenza me da oirme en el audio). También subiré a github todo el código que vayamos viendo en clase.</p>
<p>Hago esto por varios motivos:</p>
<ul>
<li>He aprendido mucho consultando información por Internet, así que en la medida de mis capacidades me gustaría contribuir a la comunidad todo lo aprendido.</li>
<li>Tengo alumnos de otras titulaciones que no tienen esta asignatura en sus planes de estudios, y me han preguntado cómo podrían aprender técnicas de desarrollo web. Este es mi granito de arena para que lo puedan hacer.</li>
<li>Con el objetivo de mejorar cada año, si hay muchos más ojos consultando el material de las clases y aportando sus críticas (constructivas), seguro que la asignatura mejora cada año.</li>
</ul>
<p>Espero que todo esto os sea de utilidad.</p>
<p>Si ves alguna incorrección, error garrafal, "cagada conceptual" o similar, no dudes en usar los comentarios para decirmelo. De lo que se trata es de aprender y mejorar, yo el primero.</p>
<p>Aquí os dejo el primer día de clase. Corresponde al "Tema 1 - Introducción".</p>
<iframe width="480" height="360" src="//www.youtube.com/embed/YFrOZokk2qk" frameborder="0" allowfullscreen></iframe>
<p><br/></p>
<iframe src="http://www.slideshare.net/slideshow/embed_code/30036167" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen> </iframe>
<p> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/micaelgallego/qu-es-la-web-30036167" title="¿Qué es la web? (Tema1: Introducción - Desarrollo Aplicaciones Web)" target="_blank">¿Qué es la web? (Tema1: Introducción - Desarrollo Aplicaciones Web)</a> </strong> from <strong><a href="http://www.slideshare.net/micaelgallego" target="_blank">Micael Gallego Carrillo</a></strong> </div></p>
¿Qué contenido debería tener una asignatura de Desarrollo Web?2014-01-12T00:00:00-08:00http://micaelgallego.github.com/blog/Contenido-asignatura-desarrollo-web<p>Muchos de nosotros nos hemos quejado siempre de la mala formación que hemos recibido en la carrera. Los comentarios habituales son: Esto no me va a servir para nada en mi trabajo, la tecnología que me cuenta el profesor está obsoleta o el profesor no tiene ningún contacto con la profesión.</p>
<p>Si un profesor de universidad te preguntara cuál sería para ti el contenido ideal de una asignatura de Desarrollo Web en una asignatura de 3º de un Ingeniería Informática, ¿Qué le contestarías? Quizás consideres que lo más importante es tener una base sólida, más que hablar de tecnologías concretas. O a lo mejor piensas que es más importante programar algo real usando una tecnología real, porque es la mejor forma de motivar al alumno y de que vea el impacto de sus decisiones. También está presente la cuestión de ¿para qué sirve la universidad? ¿Para enseñar a los alumnos las tecnologías que utlizarán en su trabajo? ¿O para inculcar unos conceptos generales, aunque eso dificulte su incorporación al mercado laboral de forma inmediata?</p>
<p>Es un tema muy complicado, posiblemente hay opiniones encontradas, pero me gustaría saber cual es vuestra opinión sobre este tema. En 3º los alumnos ya han tenido asignaturas de programación, de diseño software, de metodologías de desarrollo, algoritmia, bases de datos, pero normalmente estas asignaturas se centran tanto en su "tema" que los alumnos las perciben muchas veces como islas inconexas. ¿La asignatura de Desarrollo Web sería una buena candidata para aplicar todos los conceptos aprendidos para implementar una aplicación real?</p>
<p>Yo me he hecho todas las preguntas que os planteo a vosotros porque tengo que impartir esa asignatura. Después de sopesar los pros y contras de cada punto de vista, he diseñado el siguiente temario.</p>
<p><strong>Parte I - Historia y tecnologías de las aplicaciones web</strong></p>
<ul>
<li><p><strong>Tema 1. Introducción a las aplicaciones web (4h)</strong></p>
<ul>
<li>Introducción</li>
<li>Evolución histórica de las aplicaciones web</li>
<li>Navegadores y servidores web</li>
<li>Aplicaciones de Internet en dispositivos móviles</li>
</ul>
</li>
</ul>
<p><p/></p>
<ul>
<li><p><strong>Tema 2. Tecnologías de desarrollo de aplicaciones web (4h)</strong></p>
<ul>
<li>Introducción</li>
<li>Arquitecturas de aplicaciones web</li>
<li>Tecnologías de cliente</li>
<li>Tecnologías de servidor</li>
<li>Sistemas gestores de contenido</li>
</ul>
</li>
</ul>
<p><p/></p>
<ul>
<li><p><strong>Tema 3. Despliegue de una aplicación web (4h)</strong></p>
<ul>
<li>Introducción</li>
<li>Alojamiento</li>
<li>Cloud computing</li>
<li>Arquitecturas escalables y tolerantes a fallos</li>
</ul>
</li>
</ul>
<p><p/></p>
<p><strong>Parte II - Desarrollo de Aplicaciones Web</strong></p>
<ul>
<li><p><strong>Tema 4. Tecnologías de cliente (8h)</strong></p>
<ul>
<li>Introducción</li>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</li>
</ul>
<p><p/></p>
<ul>
<li><p><strong>Tema 5. Tecnologías de servidor (16h)</strong></p>
<ul>
<li>Introducción</li>
<li>Java Enterprise Edition (JavaEE)</li>
<li>Servlets y Java Server Pages (JSP)</li>
<li>Java Database Connectivity (JDBC)</li>
<li>Enterprise JavaBeans (EJB)</li>
<li>Java Persistence API (JPA)</li>
<li>Java Server Faces (JSF)</li>
<li>Spring</li>
</ul>
</li>
</ul>
<p><p/></p>
<ul>
<li><p><strong>Tema 6. Servicios Web con APIs REST (4h)</strong></p>
<ul>
<li>Introducción</li>
<li>Protocolo HTTP</li>
<li>JSON y XML</li>
<li>APIs REST en Java</li>
</ul>
</li>
</ul>
<p><p/></p>
<p>¿Qué te parece? ¿Qué quitarías? ¿Qué crees que falta? Recuerda que el tiempo no es infinito, son sólo 48 horas de clase y he reservado 8 horas para que se dediquen únicamente a programar (sin nada de temario).</p>
<p>Si tienes un momento, te agradecería que me dieras tu opinión. Quizás para este año ya no me de tiempo a incorporar tus sugerencias, pero posiblemente me ayuden a mejorar para el año que viene.</p>
JavaScript no es Orientado a Objetos (VTF4)2014-01-02T00:00:00-08:00http://micaelgallego.github.com/blog/JavaScript-no-es-orientado-a-objetos<p>Esta es la cuarta entrega de una serie de posts en los que cuento mi viaje por las tecnologías de front-end, esas que permiten implementar aplicaciones web interactivas. Todo ello desde el punto de vista de un programador Java con más de 10 años de experiencia. Si te interesa puedes echar un vistazo a las partes anteriores:</p>
<ul>
<li>Parte 1: <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Viaje por las tecnologias de front end</a></li>
<li>Parte 2: <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Primer contacto con JavaScript</a>,</li>
<li>Parte 3: <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">Orientacion a Objetos en JavaScript comparado con Java</a></li>
</ul>
<h1>Las características familiares de JavaScript para un desarrollador Java</h1>
<p>Después de haberme leído varios libros sobre JavaScript, entendía más o menos bien todos los conceptos del lenguaje:</p>
<ul>
<li><strong>Es un lenguaje dinámico</strong>: Entre otras muchas cosas, eso significa que no tiene compilador. Un intérprete o <em>engine</em> es el encargado de ejecutar el código fuente.</li>
<li><strong>Es un lenguaje con tipado dinámico:</strong> Eso quiere decir que las variables no tienen tipo. Una misma variable puede tener valores de diferentes tipos a lo largo de su vida.</li>
<li><strong>Tiene tres tipos básicos:</strong> Números, booleanos y cadenas de caracteres (String). Esto tiene sentido en un lenguaje que no está preocupado por la eficiencia y sí en ser muy sencillo de usar. Al fin y al cabo, la separación entre números real y entero y entre char y string son sobre todo cuestiones de eficiencia.</li>
<li><strong>Tiene un sistema de tipos unificado:</strong> De forma que un entero y un string son de la misma naturaleza.</li>
<li><strong>Tiene sentencias de control de flujo "normales":</strong> Es decir, que tiene if, while, for, switch etc.. con la sintáxis y semática a la que estamos acostumbrados los programadores Java. Incluso he visto que tiene excepciones, como en Java.</li>
<li><strong>Tiene arrays y se gestionan "por referencia":</strong> Es decir, un array es conceptualmente muy similar a como es en Java. Cuando se pasa como parámetro, se pasa la referencia (no hay copia), de forma que los cambios en el array son visibles por todos aquellos que tengan la referencia al array.</li>
<li><strong>Existe un recolector de basura:</strong> Perfecto, un comportamiento similar a Java, Python, Ruby, Scala, C#...</li>
</ul>
<p>Hasta aquí todo razonable. Estoy en un sitio conocido ;). Es cierto que no tengo mucha experiencia con lenguajes con tipado dinámico, pero siempre he entendido que si no pones el tipo a una variable, tendrás que tener mucho más cuidado de no equivocarte en el valor que asignas porque el compilador no te avisará si te equivocas. Es decir, salvo ese detalle, todo es conceptualmente similar.</p>
<h1>Programación funcional en JavaScript</h1>
<p>Una de las características importantes de JavaScript es que es un lenguaje funcional. Es funcional porque trata las funciones como ciudadanos de primera clase en el lenguaje. Se pueden declarar, se pueden invocar, se pueden guardar en variables y se pueden pasar como parámetro a otras funciones. No es funcional puro, porque puedes declarar variables y cambiar su valor y las funciones se pueden implementar sin transparencia referencial. Es decir, que pueden tener efectos colaterales y varias llamadas a la misma función pueden devolver resultados diferentes.</p>
<p>Java todavía no es un lenguaje funcional. Pero las clases anónimas han permitido programar conceptualmente de forma funcional. Librerías como <a href="http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">Guava</a> han favorecido la programación funcional con estructuras de datos. Además, como seguro que ya sabes, en Java 8 las funciones cobrarán mucha más importancia en el lenguaje a través de las <a href="http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">expresiones lambda</a>.</p>
<p>Por todo esto, la programación funcional de JavaScript es bastante natural y conocida para un desarrollador de Java como yo.</p>
<p>Sólo hay un "pequeño detalle" que diferencia las funciones de Java (sean clases anónimas o expresiones lambda) de las funciones en JavaScript. En JavaScript las funciones tienen acceso a las variables que se encuentran en el ámbito en el que se declara la función. Y si esa variable cambia de valor y se ejecuta la función, se leerá el nuevo valor. El conjunto de variables a las que tiene acceso la función se le conoce como <em>closure</em> o clousura. En Java esto no es posible, si se accede a una varible del ámbito, esa variable no puede cambiar de valor, porque en realidad se hace referencia al valor, no a la variable.</p>
<p>Que JavaScript soporte clousuras es esencial en este lenguaje. La forma de programar en JavaScript está profundamente motivada por esta característica. Al principio puede parecer un detalle más, pero como veremos más adelante, es muy importante.</p>
<h1>La orientación a objetos "clásica" en JavaScript</h1>
<p>Todas las características de JavaScript que he mencionado hasta ahora son bastante conocidas para un desarrollador Java. Es decir, un programador Java se siente bastante cómodo usando esas características porque las usa habitualmente en el desarrollo de sus programas. Siempre hay detalles que tener en cuenta, pero conceptualmente todo es bastante similar.</p>
<h2>Tres formas de implementar la orientación a objetos ¿Cual es la buena?</h2>
<p>El problema aparece cuando llegamos a la programación orientada a objetos. Según aprendía el lenguaje leí que JavaScript es un lenguaje orientado a objetos. Entonces pensé: perfecto, como en Java, Python, Ruby... Ahora sólo tenía que conocer la sintáxis. Estuve leyendo que JavaScript está basado en prototipos y no en clases. Pensé que era sólo uno de los detalles de JavaScript, pero que conceptualmente era equivalente a Java. Pero en ese momento llegaron los problemas.</p>
<p>Según leía diferentes libros y páginas de Internet me enteré de que había tres formas diferentes de implementar la orientación a objetos en JavaScript. Cada una de ellas con diferentes ventajas e inconvenientes. No entendía nada, ¿por qué hay tantas formas diferentes de implementar lo mismo? ¿Por qué no se usa una de las formas? Como no lo tenía nada claro, me puse a buscar más información por Internet, a leer más libros... pero las dudas crecían en vez de despejarse. Llegados a este punto decidí que la mejor forma de resolver mis dudas era preguntar a los desarrolladores experimentados en JavaScript que conocía. Hice un <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">estudio exahustivo de las tres formas diferentes de implementar la orientación a objetos en JavaScript</a> y recopilé las ventajas e inconvenientes de cada uno de ellos. Ese estudio serviría para poder preguntar, ¿cómo se implementa la orientación a objetos en JavaScript?</p>
<p>Con este estudio pregunté por twitter:</p>
<blockquote class="twitter-tweet" lang="es"><p>Comparación de la Orientación a Objetos en Java y JavaScript. Después de leer 4 libros no me aclaro. Me ayudas? <a href="http://t.co/5mmgyJbquI">http://t.co/5mmgyJbquI</a></p>— Micael Gallego (@micael_gallego) <a href="https://twitter.com/micael_gallego/statuses/417668476438724608">diciembre 30, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Y también pregunté en el <a href="http://www.meetup.com/madridjs/messages/62930352">grupo Meetup de MadridJS</a>.</p>
<p>Gracias a los camaradas del métal que me respondieron en la lista del meetup, a los comentarios del blog y a lo que me fueron comentando algunos amigos empecé a ver la luz.</p>
<h2>No hay una forma buena, JavaScript no es orientado a objetos</h2>
<p>Al principio las respuestas eran más confusas todavía, porque no contestaban a la pregunta. Yo pregunté cual es la mejor forma de implementar la orientación a objetos en JavaScript, pero las respuestas venían a decir que en JavaScript la orientación a objetos no es igual que en otros lenguajes y por tanto intentar aplicar los mismos conceptos que en los otros lenguajes no es la forma habitual de programar en JavaScript. Como diría alguien conocido por todos, me quedé con el culo torcío ;)</p>
<h1>La orientación a objetos "especial" de JavaScript</h1>
<p>Cuando uno lleva tanto tiempo programando con Java, tiene experiencia con patrones de diseño orientados a objetos y conoce algo de C++, Ruby y Python cree que conoce bien qué es la programación orientada a objetos. Piensa que sabe como usar este paradigma de programación para implementar programas modulares, comprensibles, con partes reutilizables y que son fácilmente ampliables y mantenibles.</p>
<p>Cuando empiezas a estudiar JavaScript crees que lo único que tienes que hacer es aprender la sintáxis para implementar las clases y esos pequeños detalles que diferencian a JavaScript de otros lenguajes que conoces. Además, como he comentado antes, yo no he tenido experiencia con lenguajes con tipado dinámico, pero pensaba que la diferencia fundamental con los lenguajes con tipado estático era que en las variables no se indica el tipo y cuando se ejecuta el programa se "verifica" si el uso de la variable es el correcto para el valor que tiene.</p>
<p>Pero estaba completamente equivocado. En JavaScript, la orientación a objetos es conceptualmente muy diferente a la orientación a objetos de Java y otros lenguajes. Por otro lado, en JavaScript los objetos son dinámicos, es decir, pueden cambiar estructuralmente durante la ejecución del programa. Al principio parece que estos dos detalles no son importantes y que conceptualmente Java y JavaScript son bastante parecidos. Pero luego te das cuenta de que esas pequeñas diferencias superficiales afectan de forma importante a la forma de programar con un lenguaje u otro.</p>
<h2>Programación orientada a objetos en Java, C#, C++, Python, Ruby...</h2>
<p>Antes de explicar cómo se implementa la orientación a objetos en JavaScript, vamos a repasar qué entendemos por orientación a objetos en los lenguajes de programación más conocidos como Java, C#, C++, Python, Ruby, etc. En estos lenguajes se utilizan las clases para definir los métodos y los atributos que tendrán los objetos de esas clases. Eso implica que todo objeto es una instancia de una clase, y esa clase define los métodos y los atributos del objeto. Si nos olvidamos de los atributos estáticos, cada objeto de una clase posiblemente tendrá valores en sus atributos diferentes a los valores de otros objetos de la misma clase. Por otro lado, los métodos serán exactamente iguales para los objetos de una misma clase.</p>
<p>En los lenguajes estáticos (Java, C++, C#) no se pueden modificar las clases en tiempo de ejecución. Es decir, no se pueden añadir o quitar atributos o métodos de los objetos de una clase durante la ejecución del programa. Ya sé que técnicamente es posible y en Java se hace en diversas situaciones especiales, pero no es una técnica que se use de forma natural en el propio lenguaje para escribir programas. En los lenguajes dinámicos como Python, Ruby, Smalltalk si se puede modificar una clase en tiempo de ejecución, aunque no sé si se utiliza habitualmente para programar o es una funcionalidad destinada a "ocasiones especiales".</p>
<h2>Programación orientada a objetos en JavaScript</h2>
<p>En JavaScript no existen las clases. En JavaScript sólo existen objetos. Pero estos objetos son muy flexibles y se les puede añadir atributos y métodos en el momento de la creación, justo después de haberlos creado o en cualquier momento a lo largo de la ejecución del programa. Esta es la clave de la programación orientada o objetos en JavaScript. Por ejemplo, si queremos crear un objeto que representa un empleado de una empresa podemos hacer lo siguiente:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">nombre</span><span class="o">:</span> <span class="s2">"Pepe"</span><span class="p">,</span>
<span class="nx">salario</span><span class="o">:</span> <span class="mi">700</span><span class="p">,</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<p>Y si queremos invocar un método o acceder a un atributo usaríamos la sintaxis a la que estamos acostumbrados en Java u otros lenguajes, la notación punto:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">texto</span> <span class="o">=</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">//Devuelve 'Nombre:Pepe, Salario:700'</span>
<span class="kd">var</span> <span class="nx">salario</span> <span class="o">=</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span> <span class="c1">//Devuelve 700</span>
</code></pre></div>
<p>En cualquier momento posterior le podemos añadir un nuevo método o atributo al objeto. Por ejemplo, podemos asignar un teléfono al empleado y un método para obtener la categoría:</p>
<div class="highlight"><pre><code class="javascript"><span class="nx">empleado</span><span class="p">.</span><span class="nx">telefono</span> <span class="o">=</span> <span class="s2">"663232539"</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">getCategoria</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span> <span class="o">></span> <span class="mi">800</span> <span class="o">?</span> <span class="s2">"Superior"</span><span class="o">:</span><span class="s2">"Normal"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Al principio te puede parecer que esta forma de trabajar con los objetos es muy rara, no es intuitiva. Pero eso es porque estás tan acostumbrado a trabajar con clases, como yo, que no entiendes muy bien qué sentido tiene hacerlo así. Pero de momento no vamos a entrar a valorar si tiene o no tiene sentido, si es mejor o es peor tener tanta flexibilidad. De momento vamos a comprender como funciona la orientación a objetos en JavaScript y al final de la entrada haremos la valoración comparando los dos modelos.</p>
<h3>Múltiples objetos con la misma estructura</h3>
<p>Cuando implementamos un programa es habitual que tengamos varios objetos estructuralmente iguales, es decir, que tengan los mismos atributos y los mismos métodos. Por eso usamos las clases en Java, para definir el molde con el que se crearán los objetos que sean instancias de esa clase. En JavaScript, si queremos que varios objetos sean estructuralmente iguales podemos encapsular el código de creación del objeto en una función. Por ejemplo, de la siguiente forma:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">function</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">nombre</span><span class="o">:</span> <span class="nx">nombre</span><span class="p">,</span>
<span class="nx">salario</span><span class="o">:</span> <span class="nx">salario</span><span class="p">,</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">empleado</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Y así podremos llamar a esa función para crear los objetos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span><span class="mi">700</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">texto</span> <span class="o">=</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">//Devuelve 'Nombre:Pepe, Salario:700'</span>
<span class="kd">var</span> <span class="nx">salario</span> <span class="o">=</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span> <span class="c1">//Devuelve 700</span>
</code></pre></div>
<p>Como ves, no hay clases por ningún sitio. Si quieres pensar que la función 'newEmpleado' es en realidad una clase, puedes hacerlo, pero estarías cometiendo el mismo error que si llamaras registo a una clase de Java. No es una clase porque no es un molde de sus objetos.</p>
<h3>Prototipos</h3>
<p>Si nos fijamos en la creación del empleado, nos damos cuenta que los atributos <code>nombre</code> y <code>salario</code> pueden tener valores diferentes para cada objeto. Pero en realidad, el método <code>toString</code> es siempre el mismo en cada objeto. Por otro lado, si quisiéramos añadir el método <code>getCategoría</code> a todos los objetos empleado que hemos creado, tendríamos que ir uno por uno y añadir el método. En estos casos sería deseable que todo aquello que compartan todos los objetos empleado estuviera en un lugar común que se gestione de forma unificada para todos ellos.</p>
<p>En JavaScript, cualquier objeto puede estar asociado a un <strong>objeto prototipo</strong>. El objeto prototipo es un objeto normal, como cualquier otro. Cuando un objeto está asociado a un prototipo se comporta de la siguiente forma:</p>
<ul>
<li>Cuando se accede a un atributo en un objeto y no existe en dicho objeto, se busca en su prototipo y se devuelve su valor.</li>
<li>Cuando se escribe en un atributo y no existe el atributo en ese objeto, se crea el atributo en el objeto. Por tanto el valor se cambia en el objeto, no en el prototipo.</li>
<li>Cuando se intenta ejecutar un método en un objeto y no existe en dicho objeto, se busca en su prototipo y se ejecuta.</li>
<li>A un objeto se le pueden añadir y quitar atributos y métodos en tiempo de ejecución, pero <a href="http://stackoverflow.com/questions/7015693/how-to-set-the-prototype-of-a-javascript-object-that-has-already-been-instantiat">no puede cambiar de prototipo</a>.</li>
</ul>
<p>Por ejemplo, si queremos que todos los empleados estén asociados a un mismo objeto prototipo que contenga los métodos (que son iguales para todos los empleados), podriamos usar un código como el siguiente:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">prototipoEmpleado</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">prototipoEmpleado</span><span class="p">);</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">empleado</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>El uso del objeto no cambia. Se podría decir que el prototipo es un detalle de implementación del objeto empleado que no afecta a los usuarios del objeto.</p>
<p>Usando un prototipo, si queremos añadir un método a todos los objetos empleado, bastaría con que añadamos el método al objeto que hace de prototipo:</p>
<div class="highlight"><pre><code class="javascript"><span class="nx">prototipoEmpleado</span><span class="p">.</span><span class="nx">getCategoria</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span> <span class="o">></span> <span class="mi">800</span> <span class="o">?</span> <span class="s2">"Superior"</span><span class="o">:</span><span class="s2">"Normal"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Por supuesto, el objeto <code>prototipoEmpleado</code> puede tener otro prototipo y así, sucesivamente. Es decir, se puede formar una <strong>cadena de prototipos</strong>.</p>
<p>Si se usan prototipos se tiene la ventaja de tener un menor consumo de memoria porque los métodos compartidos por todos los objetos estarán en el prototipo. Pero también hay un inconveniente, y es que hay una pequeña sobrecarga al ejecutar un método porque hay que buscar el método en la cadena de prototipos.</p>
<p>Es decir, no siempre se usan los prototipos en JavaScript. Por ejemplo, en los siguientes casos no se usan:</p>
<ul>
<li>Cuando sólo se necesita un objeto con unos determinados atributos y métodos.</li>
<li>Cuando el código es más sencillo y compacto si no se crea la función que permite crear objetos, aunque haya varios objetos con los mismos atributos y métodos.</li>
<li>Cuando la reducción en el tiempo de ejecución de los métodos es preferible al posible impacto en memoria que se tendría al tener los métodos en el prototipo.</li>
</ul>
<h2>Clases frente a prototipos</h2>
<p>Hemos visto como la programación orientada a objetos de Java, Ruby, Python, C++, C#... es muy diferente a la programación orientada a objetos de JavaScript. Eso es porque existen dos formas de implementar la orientación a objetos en un lenguaje de programación: <strong>basada en clases</strong> y <strong>basada en prototipos</strong>. Además de JavaScript existen más lenguajes que implementan la programación basada en prototipos, pero se usan principalmente en el ámbito académico.</p>
<p>Si estás interesado en los detalles más teóricos de un modelo frente a otro, existe mucha documentación por la red sobre el modelo de orientación a objetos basado en prototipos, sobre todo en comparación con el modelo basado en clases:</p>
<ul>
<li><a href="https://developer.mozilla.org/es/docs/Gu%C3%ADa_JavaScript_1.5/Lenguajes_basados_en_clases_frente_a_basados_en_prototipos">Documentación oficial de Mozilla</a></li>
<li><a href="http://trevinca.ei.uvigo.es/~pcuesta/publicaciones/prototipos.pdf">Artículo "Programación Orientada a Objetos: Clases versus Prototipos" en la revista Novática</a></li>
<li><a href="http://en.wikipedia.org/wiki/Prototype-based_programming">Programación basada en prototipos en la wikipedia</a></li>
</ul>
<h1>Funciones constructor, prototipos y reflexión</h1>
<p>Como JavaScript se diseñó en un momento en el que el lenguaje Java era muy popular, sus creadores intentaron que JavaScript se pareciera a Java lo más posible. Pero en vez de elegir el modelo de orientación a objetos similar a Java (como han hecho otros lenguajes dinámicos), eligieron que la sintaxis fuera parecida aunque el modelo de programación fuera diferente. Uno de los autores más reputados en el mundo de JavaScript, Douglas-Crockford, autor del libro <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a>, considera que intentar imitar la sintaxis de Java pero con otro modelo ha sido muy perjudicial para el lenguaje. Porque los desarrolladores de Java ven una sintaxis familiar y se esperan un comportamiento similar, pero los detalles de funcionamiento son muy diferentes.</p>
<h2>Función constructor y prototipo</h2>
<p>Para intentar emular a Java, si en JavaScript se llama a una función antecediendo el operador <code>new</code>, entonces se crea de forma automática un objeto, ese objeto se puede utilizar desde el cuerpo de la función usando la variable implícita <code>this</code> y además eso objeto se devuelve de forma automática al terminar de ejecutarse la función. Es decir, esta función que habíamos implementado antes:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">function</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">prototipoEmpleado</span><span class="p">);</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">empleado</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Y que se utliza usando la sintáxis:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span><span class="mi">700</span><span class="p">);</span>
</code></pre></div>
<p>Se puede implementar de la siguiente forma:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">function</span> <span class="nx">Empleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Si se llama usando la sintáxis:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span><span class="mi">700</span><span class="p">);</span>
</code></pre></div>
<p>Los objetos creados usando la función <code>Empleado</code> tendrán como prototipo el objeto <code>Empleado.prototype</code>. Es decir, si queremos que el prototipo de los objetos empleado tenga el método <code>toString</code>, tenemos que usar el siguiente código:</p>
<div class="highlight"><pre><code class="javascript"><span class="nx">Empleado</span><span class="p">.</span><span class="nx">protoype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>Como se puede ver, la función <code>Empleado</code> tiene atributos, en concreto, el atributo <code>prototype</code>. En JavaScript las funciones son objetos y como tales pueden tener atributos.</p>
<p>Cuando una función se ejecuta usando el operador <code>new</code> se dice que esa función es un <strong>constructor</strong>. Hay que tener mucho cuidado cuando se usa un constructor, porque si se ejecuta sin el operador <code>new</code> no se genera ningún error en tiempo de ejecución pero pueden ocurrir cosas inesperadas y no deseadas (otro fallo de diseño del lenguaje).</p>
<p>Como se puede ver, la sintáxis recuerda a Java, pero en realidad no hay clases, sólo hay funciones "especiales" que tienen azúcar sintáctico para crear objetos. Además, aunque se pueden usar las funciones constructor, no siempre se usan para crear objetos. En muchas ocasiones los objetos se crear con la sintaxis literal que se ha visto antes.</p>
<h2>Reflexión y duck typing</h2>
<p>En el desarrollo de un programa, en algunas ocasiones es necesario programar de forma reflexiva. En Java existen diversas formas de reflexión. La más sencilla es preguntar por la clase de un objeto, para hacer casting e invocar alguno de sus métodos. Pero también podemos preguntar por los métodos que tiene un determinado objeto (por pertenecer a una determinada clase). En JavaScript la reflexión se entiende de forma diferente.</p>
<h3>Conocer el prototipo de un objeto</h3>
<p>El lenguaje JavaScript dispone del método <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">getPrototypeOf</a> para obtener el prototipo de un objeto:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Juan"</span><span class="p">,</span><span class="mi">444</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getPrototypeOf</span><span class="p">(</span><span class="nx">empleado</span><span class="p">)</span> <span class="o">===</span> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">){</span>
<span class="c1">//... </span>
<span class="p">}</span>
</code></pre></div>
<p>Como puede haber una cadena de prototipos, se puede usar el método <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isPrototypeOf">isPrototypeOf</a> para saber si un prototipo está en la cadena de prototipos de un objeto:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Juan"</span><span class="p">,</span><span class="mi">444</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">isPrototypeOf</span><span class="p">(</span><span class="nx">empleado</span><span class="p">)){</span>
<span class="c1">//... </span>
<span class="p">}</span>
</code></pre></div>
<p>Con el objetivo de parecerse a Java, en JavaScript existe el operador <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof">instanceof</a>. Este operador sirve para saber si un determinado prototipo está en la cadena de prototipos de un objeto. Pero en vez de pasar como segundo operando el propio prototipo, se pasa la función constructor. Es decir, el código equivalente al anterior sería algo así:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Juan"</span><span class="p">,</span><span class="mi">444</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">empleado</span> <span class="k">instanceof</span> <span class="nx">Empleado</span><span class="p">){</span>
<span class="c1">//El objeto empleado tiene como prototipo al objeto Empleado.prototype.</span>
<span class="p">}</span>
</code></pre></div>
<p>Pero hay que tener en cuenta de que en JavaScript no sirve de mucho preguntar por el objeto prototipo de otro objeto. Hay veces que se utilizan objetos que no tienen prototipo, porque todos sus atributos y métodos son propiedades del propio objeto. Y esto es relativamente normal en JavaScript.</p>
<p>En Java es mucho más importante preguntar por la clase de un objeto, porque es la única forma que tenemos de conocer los métodos de ese objeto y haciendo un casting los podremos invocar. Pero en JavaScript, para poder invocar un método, basta con que ese método exista en el objeto. El método puede estar en el propio objeto o a través de su cadena de prototipos, pero eso es completamente indiferente.</p>
<h3>Duck typing</h3>
<p>Como en JavaScript no existen las clases, no tiene sentido preguntar por el tipo de un objeto, porque todos los objetos son de tipo <code>Object</code>. Podemos considerar que un objeto prototipo hace de "tipo", pero es sólo una interpretación que hacemos del funcionamiento de los prototipos cuando venimos de un lenguaje basado en clases. Pero si hubiésemos aprendido la orientación a objetos con JavaScript, el concepto de clase nos hubiese sonado muy poco intuitivo. El propio lenguaje ayuda en esta confusión, porque el operador <code>new</code>, las funciones constructor y el operador <code>instanceof</code> hacen pensar en los prototipos como una especie de clases. En perspectiva, muchos autores consideran que estos operadores han podido ser un error de diseño del lenguaje porque provoca confusión.</p>
<p>Para invocar un método en un objeto en JavaScript basta con invocar el método en el objeto. No hay que preguntar por el tipo, no hay que hacer casting, simplemente hay que ejecutar el método. Si el método existe, es que el objeto es del "tipo" esperado. Si no existe, entonces el objeto no es del tipo esperado. En realidad en JavaScript no existen clases, así que no tiene mucho sentido afirmar que un objeto es "del tipo esperado". En Python, un lenguaje con clases, se utiliza esta técnica de invocar un método en un objeto sin preocuparse por la clase del objeto. Si el método existe, perfecto, si no, se produce un error. A esta técnica se la conoce como <a href="http://es.wikipedia.org/wiki/Duck_typing">duck typing</a>. El nombre se debe a un ejemplo que se usaba para explicar este mecanismo de programación:</p>
<blockquote><p>"Cuando veo un ave que camina como un pato, nada como un pato y suena como un pato, a esa ave yo la llamo un pato."</p></blockquote>
<p>Si el método que queremos invocar no éstá disponible, se producirá un error en tiempo de ejecución. Dependiendo de cómo estemos programando nuestro programa, que el objeto no tenga el método puede suponer un error de programación o una situación aceptada. Si es un error de programación, debería corregirse. Si es una situación esperada, se podría comprobar la existencia del método antes de invocarlo o bien se podría capturar la excepción.</p>
<h1>Simulación de clases en JavaScript</h1>
<p>JavaScript no tiene clases, tiene objetos dinámicos y prototipos. Esto implica que un programa en JavaScript es muy diferente a un programa en Java.</p>
<p>En Java, un programa es un conjunto de clases que se relacionan entre sí (composición, asociación, uso y herencia). Durante la ejecución, un programa es un conjunto de objetos de esas clases que colaboran entre sí mediante las reglas marcadas por sus clases.</p>
<p>En JavaScript no hay clases, sólo hay objetos y funciones. Por tanto, la estructura del código es muy diferente. En una sección al final podremos ver cómo se estructura un programa en JavaScript, pero de momento quiero dejar claro que es de otra forma a como se hace en Java.</p>
<p>Un desarrollador Java puede intentar "emular" todo lo que conoce de la programación orientada a objetos basada en clases de Java y aplicarlo en JavaScript. De hecho, hay muchos desarrolladores que lo han hecho de esta forma. Han creado artificios en JavaScript para que el modelo de programación sea como un modelo basado en clases.</p>
<p>En concreto, existen tres formas comúnmente aceptadas de programar simulando clases en JavaScript:</p>
<ul>
<li>Clases con prototipos</li>
<li>Clases con prototipos usando librerías</li>
<li>Clases con módulos (basados en clousuras)</li>
</ul>
<p>Si quieres saber más detalles de estas formas de programar, con sus ventajas e inconvenientes, puedes echar un vistazo al <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">estudio que hice comparando cada una de ellas</a>.</p>
<p>Pero es muy importante saber que si decides estructurar tu programa con clases como lo haces en Java estarás haciendo las cosas de forma poco natural. Sobre todo si utilizas jerarquías de herencia entre clases. Los desarrolladores de JavaScript usan programación orientada a objetos porque manejan objetos dinámicos. En ciertos casos, se definen prototipos y funciones constructor, pero es más raro ver jerarquías de herencia de clases en programas JavaScript. Hace años era más habitual que los desarrollodores JavaScript intentaran estructurar un programa únicamente con clases, como en Java, pero actualmente se considera que no es una buena práctica, porque las características del lenguaje permiten programar de otra forma más directa, concisa y versátil.</p>
<p>Es como si un desarrollador de C programara en Java con clases sin atributos y con métodos estáticos (como módulos) y con clases con atributos públicos y sin métodos (como structs). Estaría implementando programación estructurada en Java. Lo mismo les ocurre a los programadores de C que usan <a href="http://es.wikipedia.org/wiki/GObject">GObject</a>, la librería de objetos de la gente de GNOME. Han montado un sistema de objetos encima del lenguaje C. No está mal, cumple sus objetivos, pero es un artificio sobre el lenguaje.</p>
<p>Otra cosa muy importante es que tu puedes programar con el artificio que tu quieras. Pero si quieres leer código de otros, tendrás que comprender su funcionamiento, y es bastante probable que ellos no usen el mismo artificio que tu, porque hay miles de formas diferentes de simular clases en JavaScript. Si vas a programar en equipo tendrás que acordar con tus compañeros una forma de programar, y es posible que no se utilice la forma que a ti más te gusta. Es decir, que sea como sea, tendrás que conocer en profundidad cómo funciona JavaScript y los idiomas aceptados en este lenguaje.</p>
<h1>CoffeScript y sus clases</h1>
<p>Hay muchos programadores que piensan que la sintáxis de JavaScript es muy verbosa y no es la más adecuada para un lenguaje dinámico. Estos programadores suelen utilizar otros lenguajes dinámicos como Ruby y Python y languajes funcionales como Haskell.</p>
<p>Para sentirse más cómodos, estos desarrolladores han creado el lenguaje de programación <strong><a href="http://coffeescript.org/">CoffeScript</a></strong>, un lenguaje que se traduce a JavaScript. Su regla de oro es que "Es sólo JavaScript" y se puede considerar como azucar sintáctico sobre JavaScript. En general mantiene los mismos conceptos que JavaScript. Es decir, no lo utliza como si fuera el <a href="http://www.hanselman.com/blog/JavaScriptIsWebAssemblyLanguageAndThatsOK.aspx">ensamblador de la web</a>, simplemente es una fina capa por encima. De hecho, algunos piensan que para usar CoffeeScript <a href="http://carlossanchezperez.wordpress.com/2013/06/16/antes-de-meterte-en-coffeescript-recomendable-haber-pasado-por-javascript-primera-parte/">primero tienes que saber JavaScript</a>, cosa que yo he experiementado en mis propias carnes. En otros contextos, no tendría sentido hacer un lenguaje como CoffeeScript, tendría más sentido hacer un lenguaje completamente nuevo, pero la web es un sitio muy especial ;).</p>
<p>Aparte de todo el azúcar sintáctico, una de las cosas que pretende mejorar CoffeeScript es la <a href="http://coffeescript.org/#classes">sintaxis para crear clases</a>. En CoffeeScript se pueden implementar clases apoyándose en los prototipos de JavaScript, pero con una sintaxis mucho más parecida a los lenguajes que realmente tienen clases. Puedes implementar clases con <code>class</code>, <code>extends</code> y <code>super</code>.</p>
<p>Pero CoffeeScript no te fuerza a estructurar tu programa con clases, simplemente te facilita el uso de prototipos como si fueran clases con una sintáxis más concisa. Pero si prefieres trabajar directamente con prototipos, también te ofrece operadores para tratar directamente con ellos.</p>
<h1>Estructura de una aplicación JavaScript</h1>
<p>La estructura de una aplicación depende de muchos factores. En Java se pueden tener diversos tipos de aplicaciones, por mencionar algunas:</p>
<ul>
<li><strong>Aplicación de escritorio con Swing</strong>: En este caso lo más probable es que la aplicación sea una colección de clases relacionadas entre sí y una de ellas tendrá un método estático <code>main</code> que contendrá las sentencias que incian la ejecución de la aplicación. Posiblemente no haya ningún fichero de configuración.</li>
<li><strong>Aplicación web con Spring</strong>: Lo más probable es que, además de las clases que forman la aplicación, tengamos dos ficheros de configuración: <code>web.xml</code> y <code>application-context.xml</code>.</li>
</ul>
<p>En JavaScript ocurre lo mismo, dependiendo del tipo de aplicación, la estructura será muy diferente. Pero sea como sea la estructura de la aplicación, hay que tener en cuenta que no hay clases. Por tanto, la aplicación estará estructurada con otros elementos de alto nivel.</p>
<p>Si consideramos la aplicación más básica en JavaScript que se ejecuta en el navegador posiblemente usará la librería <a href="http://jquery.com/">jQuery</a> y <a href="http://underscorejs.org/">underscore.js</a>. En el momento de escribir este post, estas librerías se consideran esenciales (al menos esa es la sensación que tengo). La aplicación tendrá la siguiente estructura:</p>
<p><code>index.html</code></p>
<div class="highlight"><pre><code class="html"><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"http://code.jquery.com/jquery-1.7.2.js"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"http://underscorejs.org/underscore.js"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"app.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"primenumbers"</span><span class="nt">></span>Prime numbers<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"theirsquares"</span><span class="nt">></span>Their squares<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div>
<p><code>app.js</code></p>
<div class="highlight"><pre><code class="javascript"><span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">primeNumbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">11</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">listIn</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">selector</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span>
<span class="nx">$</span><span class="p">(</span><span class="nx">selector</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="s1">'<p>'</span> <span class="o">+</span> <span class="nx">num</span> <span class="o">+</span> <span class="s1">'</p>'</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">primeNumbers</span><span class="p">,</span> <span class="nx">listIn</span><span class="p">(</span><span class="s1">'#primenumbers'</span><span class="p">));</span>
<span class="kd">var</span> <span class="nx">square</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">num</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">num</span> <span class="o">*</span> <span class="nx">num</span><span class="p">;</span> <span class="p">};</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">primeNumbers</span><span class="p">,</span> <span class="nx">square</span><span class="p">),</span> <span class="nx">listIn</span><span class="p">(</span><span class="s1">'#theirsquares'</span><span class="p">));</span>
<span class="p">});</span>
</code></pre></div>
<p>Si no tienes experiencia con JavaScript y con las librerías jQuery y underscore, este código te puede parecer un poco difícil de entender. A continuación se muestran algunas claves:</p>
<ul>
<li>Los símbolos <code>$</code> y <code>_</code> son identificadores que usan la librería jQuery y underscore para declarar sus utilidades. Se usan estos nombres tan cortos para que sean muy sencillos de usar en un programa.</li>
<li><code>$</code> es una función definida globalmente por jQuery. La expresión <code>$(selector).append(...)</code> es la invocación de una función que devuelve un objeto en el que se invoca el método <code>append</code>.</li>
<li><code>_</code> es un objeto definido globalmente por la librería underscore, por eso la expresión <code>_.each(...)</code> es la invocación de un método del objeto <code>_</code>.</li>
<li>El código de la aplicación está en una función anónima que se pasa como parámetro a la función <code>$</code>. La función pasada como parámetro será invocada cuando el documento se haya cargado en el navegador, pero sin necesidad de que se hayan cargado todas las imágenes y recursos asociados.</li>
</ul>
<p>Como se puede ver, la estructura de la aplicación no se parece nada a un conjunto de clases que colaboran entre sí. Por tanto, aunque utilices clases en tu aplicación, será sólo en ciertas partes de la misma, pero las clases no definirán la estructura como lo harían en un programa Java.</p>
<h1>Conclusiones</h1>
<p>Cuando empecé a aprender de JavaScript pensaba que era un lenguaje parecido a Java, salvo por ser de tipado dinámico en vez de tipado estático. Esta confusión quizás se debió a que llevo mucho tiempo programando con Java y en mis pinitos con Ruby y Python las cosas eran bastante naturales para mí porque todos los lenguajes se parecían bastante.</p>
<p>También he de decir que los libros que he leído no me han ayudado mucho. Quizás ha sido mi ceguera conceptual y lo que ahora entiendo estaba perfectamente especificado en los libros, pero me da la sensación de que algunos de los libros que he leído no respondían a las preguntas que yo me estaba haciendo o las respuestas que obtenía me llevaban a sacar conclusiones equivocadas.</p>
<p>En cualquier caso, ahora ya lo entiendo todo. La orientación a objetos que yo he practicado durante tanto tiempo no es la única que existe. Existen otros lenguajes que siendo orientados a objetos, no tienen clases, y eso lo cambia todo. Es posible que haya partes de un programa JavaScript que resulten familiares a un desarrollador acostumbrado a usar la orientación a objetos de clases en Java. Pero sin duda alguna, la estructura del programa JavaScript nada tiene que ver con la estructura de un programa Java.</p>
<p>Ya he entendido las características del lenguaje JavaScript, pero todavía no las puedo valorar. Hasta que no lleve un tiempo programando con JavaScript, no podré tener una opinión. Quizás me enamore de esa versatilidad y libertad prácticamente total que me ofrece el lenguaje, y cuando tenga que programar en Java me sienta encorsetado en una estructura rígida y llena de protocolo y ceremonia. O quizás me pase justo lo contrario, que esa libertad me haga muy difícil entender código JavaScript de otros desarrolladores o que yo mismo vaya mucho más lento programando por no tener claro cómo hacer esto o lo otro.</p>
<p>Dentro de un tiempo os contaré mis impresiones ;). Si quieres, puedes compartir con nosotros tu experiencia en los comentarios.</p>
<div id="note">
<p>Este post forma parte de una de una serie de posts en los que cuento mi viaje por las tecnologías de front-end, esas que permiten implementar aplicaciones web interactivas. Todo ello desde el punto de vista de un programador Java con más de 10 años de experiencia. Si te interesa puedes echar un vistazo a las demás entradas:</p>
<ul>
<li>Parte 1: <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Viaje por las tecnologias de front end</a></li>
<li>Parte 2: <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Primer contacto con JavaScript</a>,</li>
<li>Parte 3: <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">Orientacion a Objetos en JavaScript comparado con Java</a></li>
<li>Parte 4: <a href="/blog/JavaScript-no-es-orientado-a-objetos">JavaScript no es orientado a objetos</a></li>
</ul>
</div>
Orientación a Objetos en JavaScript comparado con Java (VTF3)2013-12-30T00:00:00-08:00http://micaelgallego.github.com/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java<p>Esta es mi tercera entrada en la serie de posts <strong>Viaje por las tecnologías de Front-end</strong>. Si tienes interés, puedes echar un vistazo a la <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Parte 1</a> y la <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Parte 2</a>.</p>
<p>Yo soy desarrollador Java hace más de 10 años. Aprendí programación orientada a objetos en la universidad (EUI-UPM) de la mano de Luis Fernández, uno de los mejores profesores que he tenido. Era una época en la que la orientación a objetos no era <em>main stream</em> y costaba mucho encontrar material de calidad sobre el tema. Había muchos desarrolladores que no sabían utilizar de forma adecuada la orientación a objetos. De hecho, leyendo libros como <a href="http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683">Effective Java Programming</a> te das cuenta de que hace 15 años incluso los mejores ingenieros no tenían claros algunos aspectos de la programación orientada a objetos (clases Date, Stack, etc...). Afortunadamente, creo que ahora hay un consenso generalizado sobre utilizar de forma adecuada la orientación a objetos para desarrollar programas modulares y legibles, lo que favorece su desarrollo y mantenimiento.</p>
<p>Partiendo de ese <em>background</em>, una de las cosas que menos me gusta de JavaScript es que no hay un consenso sobre la mejor forma de implementar la orientación a objetos. Sobre todo en las jerarquías de herencia. De hecho, hay algunos desarrolladores (como el autor del libro [JavaScript: The Good Parts][]) que indican que las jerarquías de herencia tienen mucho menos sentido en lenguajes con tipado dinámico (como JavaScript). Otro síntoma de que no hay consenso en cómo usar la orientación a objetos en JavaScript es que hay múltiples librerías que facilitan la definición de clases.</p>
<p>En este post he recopilado toda la información que he encontrado en fuentes fiables de Internet y en buenos libros de JavaScript sobre la orientación a objetos con JavaScript. A ver si de esa forma puedo entender cual es la mejor forma de estructurar y reutilizar código para que sea mantenible usando los principios de la orientación a objetos.</p>
<p>Como supongo que ya sabes, en JavaScript hay 125 formas de conseguir que un programa se comporte de una determinada forma. Hay cierto consenso en que 75 formas no son adecuadas, pero todavía quedan otras 50 formas de hacerlo "razonable". Este post no pretende ser un repaso a todos y cada uno de los detalles que permiten tener el mismo resultado en JavaScript. Si quieres conocer esos detalles, lo mejor será que te leas 4 o 5 buenos libros ;).</p>
<p>Si no tienes mucha experiencia con JavaScript (como yo), te recomiendo que eches un vistazo a mi post con una <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">introducción a JavaScript para programadores Java</a>.</p>
<p>Para preparar este post me he basado en las siguientes páginas y libros:</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">Documentación oficial de Mozilla</a> (2010 con ajustes posteriores)</li>
<li><a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript">Patrón Módulo en JavaScript</a></li>
<li><a href="http://msdn.microsoft.com/en-us/magazine/cc163419.aspx">Página del MSDN Magazine</a> (Mayo 2007)</li>
<li>Libro <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a> (Mayo 2008)</li>
<li>Libro <a href="http://www.manning.com/resig/">Secrets of the JS Ninja</a> (2013)</li>
<li>Libro <a href="http://effectivejs.com/">Effective JavaScript</a> (Noviembre 2012)</li>
<li>Libro <a href="http://eloquentjavascript.net/">Eloquent JavaScript</a> (Julio 2007)</li>
<li>StackOverflow <a href="http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript#1598077">How to properly create a custom object in javascript</a></li>
<li>StackOverflow <a href="http://stackoverflow.com/questions/7486825/javascript-inheritance">JavaScript Inheritance</a></li>
</ul>
<h1>Creación de clases independientes (sin herencia)</h1>
<p>Para que sea más sencillo de entender los diferentes modelos, primero describiré como crear una clase que no haga uso de una jerarquí de herencia. Posteriormente veremos cómo se hace herencia con cada uno de los modelos.</p>
<h2>Clases en Java</h2>
<p>Si no consideramos los métodos y atributos estáticos, una clase en Java es una descripción de los métodos y atributos que tendrán los objetos de dicha clase. Es decir, todo objeto es una instancia de una clase, que define sus métodos y sus atributos. Cada objeto tendrá valores diferentes para sus atributos, pero todos los objetos compartirán los mismos métodos.</p>
<p>Por ejemplo, si queremos representar empleados en un programa Java, la clase <code>Empleado</code> se definiría así:</p>
<div class="highlight"><pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Empleado</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">nombre</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">double</span> <span class="n">salario</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">Empleado</span><span class="o">(</span><span class="n">String</span> <span class="n">nombre</span><span class="o">,</span> <span class="kt">double</span> <span class="n">salario</span><span class="o">){</span>
<span class="k">this</span><span class="o">.</span><span class="na">nombre</span> <span class="o">=</span> <span class="n">nombre</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">salario</span> <span class="o">=</span> <span class="n">salario</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">(){</span>
<span class="k">return</span> <span class="s">"Nombre:"</span><span class="o">+</span><span class="n">nombre</span><span class="o">+</span><span class="s">", Salario:"</span><span class="o">+</span><span class="n">salario</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<p>Y así se crearía un objeto de esa clase y se usarían sus métodos:</p>
<div class="highlight"><pre><code class="java"><span class="n">Empleado</span> <span class="n">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Empleado</span><span class="o">(</span><span class="s">"Juan"</span><span class="o">,</span><span class="mi">800</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span> <span class="n">empleado</span><span class="o">.</span><span class="na">toString</span><span class="o">()</span> <span class="o">);</span>
</code></pre></div>
<p>Como se puede ver, en Java la visibilidad de los elementos es un concepto importante. La clase y sus métodos son públicos (se pueden usar desde cualquier parte del programa), mientras que los atributos son privados (sólo se pueden usar desde la implementación de la clase).</p>
<h2>Clases con prototipos en JavaScript</h2>
<p>En JavaScript no existe el concepto de clase. Es decir, no existe una descripción de los métodos y los atributos que tendrá un objeto. Para que un objeto tenga atributos, basta con dar un valor inicial a una propiedad del objeto con el nombre que queramos para el atributo. Para que un objeto tenga métodos, basta con asignar a una propiedad del objeto una función. En definitiva, en JavaScript sólo hay objetos y funciones.</p>
<p>Para optimizar el consumo de memoria y el tiempo de ejecución, existe el concepto de prototipo. Todo objeto en JavaScript tiene asociado un objeto especial llamado "prototipo". Cuando se accede a un atributo o se invoca un método de un objeto y el objeto no tiene dicho atributo o método, se busca en su prototipo. Además, un prototipo puede tener a su vez otro prototipo, creando una "cadena de prototipos".</p>
<p>Aunque existen diversas formas de usar los prototipos en JavaScript, lo más aceptado es que una clase se represente de la siguiente forma:
* Los atributos se asocian al nuevo objeto en la función constructor (que crea el objeto y le asocia el prototipo).
* Los métodos se asocian al prototipo.</p>
<p>Como en el lenguaje JavaScript no existen las clases, no hay consenso sobre lo que es una clase en JavaScript. Si usamos el patrón de clases con prototipos, podemos decir que una clase es su función constructor y el código que asocia los métodos al prototipo.</p>
<p>Siguiendo este criterio, la clase empleado se crearía:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getNombre</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getSalario</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>Y para crear un objeto empleado y usar sus métodos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<p>Una diferencia entre JavaScript y Java es que en JavaScript todos los atributos y métodos son accesibles desde cualquier parte del programa. En terminología de Java, todos los atributos y métodos son públicos. En realidad, la visibilidad de los elementos es una documentación que escribe el desarrollador que crea la clase y que se verifica por el compilador. El desarrollador dice que un método es privado porque no quiere que nadie use el método de forma que pueda combiarlo en el futuro si lo necesita. Eso también permite abstrar el usuario de la clase de detalles que no son relevantes para él.</p>
<p>En JavaScript no hay compilador que proteja los elementos privados. Pero tampoco existen mecanismos para que se genere un error en ejecución que impida a un cliente acceder a atributos o métodos privados. Lo único que se puede hacer es documentar la clase de forma adecuada y esperar que el cliente se lea la documentación y la haga caso ;).</p>
<p>Pero ese no es el problema más grave. El principal problema es que en JavaScript todo es dinámico (no sólo el tipo de las variables). Cualquier código que esté utilizando un objeto puede cambiar ese objeto de forma radical en tiempo de ejecución. En concreto, puede hacer lo siguiente:</p>
<ul>
<li>Puede añadir atributos al objeto.</li>
<li>Puede quitar atributos al objeto, incluso aquellos que se establecieron en la función constructor.</li>
<li>Puede añadir métodos al objeto.</li>
<li>Puede añadir atributos al prototipo de un objeto, haciendo que todos los objetos de esa clase (que comparten el prototipo) tengan un nuevo atributo con el mismo valor.</li>
<li>Puede añadir métodos al prototipo de un objeto, haciendo que todos los objetos de esa clase (que comparten el prototipo) tengan un nuevo método.</li>
</ul>
<p>Con esta extrema flexibilidad, la única forma de que el programa sea fácil de entender y por tanto de desarrollar y mantener, es leer bien la documentación y usar cada objeto como el desarrollador quiere que se use. En concreto, si no hay buenas razones para hacerlo, no se debería modificar estructuralmente un objeto ni sus prototipos. Además, no se deberá acceder directamente a los atributos de un objeto si existen métodos para hacerlo, porque eso será una señal de que esos atributos pueden ser un detalle de implementación que puede cambiar en el futuro (aka, atributos privados).</p>
<p>Para paliar esta extrema flexibilidad, recientemente se han añadido mecanismos para evitar que los atributos se puedan alterar una vez construido el objeto. Estos mecanismos de protección sólo se aplican si se usa el <a href="http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/">modo estricto de JavaScript</a>. Para más información sobre estas características conviene consultar la <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">página oficial de Mozilla</a> y el <a href="http://ejohn.org/blog/ecmascript-5-objects-and-properties/">blog del creador de jQuery</a>. No obstante, no he visto la forma de utilizar estos mecanismos para crear clases más seguras. El principal problema es que los mecanismos de protección del objeto no están pensados para utilizarse en un contexto en el que hay jerarquías de herencia entre objetos. No sé, quizás esté equivocado.</p>
<p>Existen muchas variantes al código que se ha mostrado para implementar clases como prototipos. A continuación se describen algunas de ellas:</p>
<ul>
<li>Si no se usa el operador <code>new</code> al crear el objeto y se llama directamente a la función, no se produce ningún error en tiempo de ejecución pero ocurren muchas cosas inesperadas. En el Item 33 del <a href="http://effectivejs.com/">Effective JavaScript</a> tienes algunos consejos para generar un error o para que se comporte de forma adecuada aunque no uses <code>new</code>. Usar estas técnicas depende de lo <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_defensiva">defensivo</a> que quieras ser programando.</li>
<li>Los métodos se pueden guardar en el objeto en vez de en su prototipo con el objetivo de que la invocación del método sea más rápida (ya que se evitaría la búsqueda en el prototipo). Según comentan en <a href="http://effectivejs.com/">Effective JavaScript</a> parece que eso podría aumentar el consumo de memoria de cada objeto y no se reduciría de forma aprecible el tiempo de ejecución porque la ejecución de métodos suele estar optimizada.</li>
</ul>
<p>Aunque esta es la forma original de implementar clases, los desarrolladores han ideado formas que permiten sortear los problemas que presenta este patrón.</p>
<h2>Clases con módulos en JavaScript</h2>
<p>Algunos programadores consideran que es inaceptable que JavaScript no permita controlar la visibilidad de los atributos y los métodos. Para sortear el problema han usado una técnica que permite crear objetos con atributos privados y con métodos públicos y privados. Además, aunque no se evite completamente, se reducen los cambios estructurales que se le pueden hacer a un objeto.</p>
<p>La técnica se conoce como <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript">Patrón Módulo</a> y aunque se puede aplicar en otros contextos, se utiliza para encapsular atributos y métodos de objetos. Esta técnica se basa en el hecho de que una función captura las variables que tiene a su alcance y siempre que sea llamada esa función podrá acceder a dichas variables. A esto se le conoce como <em>closure</em>.</p>
<p>A continuación se presenta una clase implementada usando esta técnica:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">_nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">getNombre</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">_nombre</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">getSalario</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">_salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">toString</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="nx">_nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="nx">_salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">getNombre</span> <span class="o">=</span> <span class="nx">getNombre</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">getSalario</span> <span class="o">=</span> <span class="nx">getSalario</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="nx">toString</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">that</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Y para crear un objeto empleado y usar sus métodos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<p>Si analizamos el código, podemos darnos cuenta de los siguientes detalles:</p>
<ul>
<li>La función <code>newEmpleado</code> no se llama usando el operador <code>new</code>, por tanto, estrictamente hablando, no es un constructor.</li>
<li>El nuevo objeto se crea como un objeto literal dentro de la función, por tanto su prototipo es <code>Object.prototype</code>.</li>
<li>El nuevo objeto no tiene los atributos como propiedades. Los atributos se representan como variables locales de la función <code>newEmpleado</code>. A estas variables locales tienen acceso todas las funciones que hacen de métodos del objeto porque forman parte de su closure.</li>
<li>Los métodos del nuevo objeto se guardan como propiedades en el propio objeto, no en su prototipo. Esto se debe a que los métodos son específicos para ese objeto, porque tienen acceso directo a las variables que actúan como atributos.</li>
<li>En la implementación de los métodos no se utiliza el objeto implícito <code>this</code> para acceder a los atributos.</li>
</ul>
<p>Este patrón de clases como módulos tiene las siguientes ventajas frente al patrón original de clases como prototipos:</p>
<ul>
<li>Los atributos son privados. Es decir, desde un código que usa el objeto no se puede modificar directamente el valor de los atributos. Tampoco se pueden borrar.</li>
<li>Se pueden poner métodos privados no accesibles por los clientes del objeto. Basta con que esos métodos no se establezcan como propiedades del objeto <code>that</code>.</li>
<li>No hay forma de modificar los métodos de todos los objetos de una clase porque la clase no se representa con un prototipo. Es decir, al estar todos los métodos como propiedades del propio objeto, cada objeto es independiente.</li>
</ul>
<p>Algunos de los "puntos débiles" del patrón de clases como prototipos siguen estando presentes en el patrón de clases como módulos:</p>
<ul>
<li>Cualquier código que tenga acceso a un objeto, puede borrar los métodos o sustituirlos por otros.</li>
</ul>
<p>Además, existen algunos inconvenientes al implementar las clases como funciones:</p>
<ul>
<li>El consumo de memoria puede ser importante debido a que cada objeto tiene sus propios métodos (en vez de ser propiedades del objeto prototipo compartido por todos los objetos de la clase).</li>
<li>El valor de los atributos no es visible en los depuradores (al menos en el de Google Chrome) porque no son propiedades del objeto.</li>
<li>Este patrón requiere un poco más de código que el patrón original, lo que puede dar lugar a más complejidad en el desarrollo y mantenimiento.</li>
</ul>
<h2>Clases con librerías en JavaScript</h2>
<p>Como ya se ha visto, la orientación a objetos basada en prototipos de JavaScript es diferente a la orientación a objetos basada en clases de Java y otros lenguajes. No obstante, una vez que comprendes el funcionamiento de los prototipos comprendes que si te abstraes un poco, son conceptualmente muy similares. Es decir, puedes obtener esencialmente el mismo comportamiento. Pero como se ha visto en los ejemplos de código, la sintaxis para crear una clase con prototipos puede ser confusa, propensa a errores y verbosa. Además, crear jerarquías de herencia es todavía más complicado (como se verá más adelante).</p>
<p>Debido a todos estos aspectos, hace unos años empezaron a surgir librerías en JavaScript que permiten definir clases de forma que el código se parece a como se definen las clases en lenguajes como Java. En el libro <a href="http://www.manning.com/resig/">Secrets of the JS Ninja</a> se dice que estas librerías implementan "técnicas de simulación de herencia clásica", porque donde más ayudan es en la creación de jerarquías de herencia. En el libro <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a> también se utiliza el término "herencia clásica".</p>
<p>Algunas de las librerías ofrecen mucha más funcionalidad, pero aquí sólo estamos interesados en la definición de clases. A continuación se presenta la sintaxis que se usa en algunas de las librerías más relevantes y actualizadas como <a href="http://prototypejs.org/">Prototype.js</a> y <a href="http://jsclass.jcoglan.com/">JS.Class</a>. No obstante, hay bastantes más librerías que permiten crear clases como <a href="http://code.google.com/p/base2/">Base2</a>, <a href="http://joose.it/">Joose</a>, <a href="https://github.com/ded/klass]">klass</a>, <a href="http://mootools.net/docs/core/Class/Class]">Mootools</a>, <a href="https://github.com/Gozala/selfish">selfish</a>, <a href="http://classy.pocoo.org/">classy</a>, <a href="http://manual.qooxdoo.org/1.4.x/pages/core/classes.html">qooxdoo</a>, <a href="http://yuilibrary.com/yui/docs/yui/yui-extend.html">yui</a> y <a href="http://indigounited.com/dejavu/">dejavu</a>.</p>
<p>Para comprender cómo funcionan estas librerías se pueden consultar las siguientes referencias:</p>
<ul>
<li>En el libro <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a> y en <a href="http://javascript.crockford.com/inheritance.html">esta web de su autor</a>.</li>
<li>En el libro <a href="http://www.manning.com/resig/">Secrets of the JS Ninja</a> y en <a href="http://ejohn.org/blog/simple-javascript-inheritance/">este post del autor</a>.</li>
<li>En <a href="http://stackoverflow.com/questions/7486825/javascript-inheritance]">este hilo de StackOverflow</a>.</li>
</ul>
<p>No he revisado todas las librerías, pero creo que la gran mayoría de ellas sólo introducen azucar sintáctico para crear clases con prototipos. No he visto ninguna librería que ayude a crear clases con módulos.</p>
<h3>Prototype.js</h3>
<p>Con esta librería se crean clases como prototipos pero con una sintáxis inspirada en lenguajes como Java. Por ejemplo, la clase Empleado se crearía así:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">Empleado</span> <span class="o">=</span> <span class="nx">Class</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getNombre</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getSalario</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div>
<p>Y un objeto se crearía y usaría de la misma forma que las clases basadas en prototipos. Al fin y al cabo, es sólo azucar sintáctico al crear los objetos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<h3>JS.Class</h3>
<p>Esta librería es relativamente reciente y pretende simular en JavaScript la forma de definir clases en Ruby. Sigue la misma filosofía que las librerías anteriores. La clase empleado definida con esta librería se implementaría:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">Empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Class</span><span class="p">({</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getNombre</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getSalario</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div>
<p>Y los objetos se usarían de la misma forma que con clases basadas en prototipos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<h1>Herencia de clases</h1>
<p>Una de las características más innovadoras de la programación orientada a objetos frente a los paradigmas de programación previos es la capacidad de implementar jerarquías de clasificación de conceptos utilizando la herencia de clases. Esta potente técnica de programación permite definir una clase ampliando otra clase previamente definida. Además, en ciertos casos, parte del comportamiento definido en la clase base se redefine para adaptarlo a las peculiaridades de las clases hijas.</p>
<p>Veamos cómo se pueden implementar jerarquías de herencia en Java y en JavaScript con cada uno de los patrones de implementación de clases.</p>
<h2>Herencia de clases en Java</h2>
<p>Para implementar una jerarquía de herencia en Java basta crear una clase hija que <code>extends</code> de la clase padre. Supongamos que queremos implementar una clase Jefe que herede de empleado. Vamos a añadir un atributo <code>despacho</code>. Además, vamos a redefinir el método <code>toString</code> reutilizando la implementación de <code>toString</code> de la clase padre.</p>
<p>Se muestra la clase Empleado de nuevo:</p>
<div class="highlight"><pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Empleado</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">nombre</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">double</span> <span class="n">salario</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">Empleado</span><span class="o">(</span><span class="n">String</span> <span class="n">nombre</span><span class="o">,</span> <span class="kt">double</span> <span class="n">salario</span><span class="o">){</span>
<span class="k">this</span><span class="o">.</span><span class="na">nombre</span> <span class="o">=</span> <span class="n">nombre</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">salario</span> <span class="o">=</span> <span class="n">salario</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">(){</span>
<span class="k">return</span> <span class="s">"Nombre:"</span><span class="o">+</span><span class="n">nombre</span><span class="o">+</span><span class="s">", Salario:"</span><span class="o">+</span><span class="n">salario</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<p>La clase hija Jefe se implementaría:</p>
<div class="highlight"><pre><code class="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Jefe</span> <span class="kd">extends</span> <span class="n">Empleado</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">despacho</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">Jefe</span><span class="o">(</span><span class="n">String</span> <span class="n">nombre</span><span class="o">,</span> <span class="kt">double</span> <span class="n">salario</span><span class="o">,</span> <span class="n">String</span> <span class="n">despacho</span><span class="o">){</span>
<span class="kd">super</span><span class="o">(</span><span class="n">nombre</span><span class="o">,</span> <span class="n">salario</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">despacho</span> <span class="o">=</span> <span class="n">despacho</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">(){</span>
<span class="k">return</span> <span class="kd">super</span><span class="o">.</span><span class="na">toString</span><span class="o">()+</span><span class="s">" Despacho:"</span><span class="o">+</span><span class="k">this</span><span class="o">.</span><span class="na">despacho</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div>
<p>Y así se crearía un objeto de esa clase y se usarían sus métodos:</p>
<div class="highlight"><pre><code class="java"><span class="n">Jefe</span> <span class="n">jefe</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Jefe</span><span class="o">(</span><span class="s">"Pepe"</span><span class="o">,</span> <span class="mi">700</span><span class="o">,</span> <span class="s">"E12"</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span> <span class="n">jefe</span><span class="o">.</span><span class="na">toString</span><span class="o">()</span> <span class="o">);</span>
</code></pre></div>
<h2>Herencia de clases con prototipos en JavaScript</h2>
<p>Para implementar una jerarquía de herencia con prototipos en realidad lo que hay que hacer es una cadena de prototipos. El primer elemento de la cadena será el objeto, su prototipo será el objeto de la clase hija y el prototipo de ésta será el objeto de clase padre.</p>
<p>Se incluye la clase Empleado de nuevo para recordar su implementación:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getNombre</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getSalario</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>La implementación de la clase Jefe sería:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Jefe</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">,</span> <span class="nx">despacho</span><span class="p">){</span>
<span class="c1">//Llamada al constructor padre</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="nx">despacho</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Conexión de prototipo clase hija a clase padre</span>
<span class="nx">Jefe</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="nx">Jefe</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="c1">//Llamada a método redefinido</span>
<span class="k">return</span> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">)</span><span class="o">+</span><span class="s2">" Despacho:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">despacho</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>Y para crear un objeto jefe y usar sus métodos:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">jefe</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Jefe</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">,</span> <span class="s2">"E12"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">jefe</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<p>Con la implementación mostrada, el objeto tiene todos sus atributos como propiedades del propio objeto. Estas propiedades se establecen en las llamadas que se hacen a los constructores de la jerarquía de herencia. A diferencia de Java, en JavaScript es necesario llamar al constructor de la clase padre de forma explícita, aunque no tenga parámetros.</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Jefe</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">,</span> <span class="nx">despacho</span><span class="p">){</span>
<span class="c1">//Llamada al constructor padre</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="nx">despacho</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>A diferencia de los atributos, los métodos son propiedades de los prototipos. Para crear la jerarquía de herencia hay que hacer que el prototipo de los objetos de la clase Jefe sea un objeto de la clase Empleado. Esto se consigue con la siguiente sentencia:</p>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//Conexión de prototipo clase hija a clase padre</span>
<span class="nx">Jefe</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
</code></pre></div>
<p>De esta forma, cuando un método no están en un prototipo, se busca en el siguiente de la cadena. Esto optimiza el consumo de memoria y según parece la búsqueda de los métodos en la cadena de prototipos está bastante optimizada, así que no hay mucho impacto en la ejecución.</p>
<p>Por último, para redefinir un método basta con asignar una nueva función en el prototipo de la clase hija que "oculta" la función del prototipo de la clase padre cuando se realiza la búsqueda.</p>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Jefe</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">)</span><span class="o">+</span><span class="s2">" Despacho:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">despacho</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>Además, si en la implementación del método redefinido se quiere llamar al método original, basta con hacer esa llamada de forma explícita usando una referencia al protototipo de la clase padre, que es el que contiene el método.</p>
<h2>Herencia de clases con módulos en JavaScript</h2>
<p>Si se implementan las clases como módulos también se pueden crear jerarquías de herencia. Como hemos hecho antes, se incluye aquí la implementación de la clase Empleado para recordar la implementación:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">_nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">getNombre</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">_nombre</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">getSalario</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">_salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">toString</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="nx">_nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="nx">_salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">getNombre</span> <span class="o">=</span> <span class="nx">getNombre</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">getSalario</span> <span class="o">=</span> <span class="nx">getSalario</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="nx">toString</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">that</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Para implementar una clase hija Jefe que añade un atributo y redefine el método toString es la siguiente:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">newJefe</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">,</span> <span class="nx">despacho</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salarion</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">_despacho</span> <span class="o">=</span> <span class="nx">despacho</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">super_toString</span> <span class="o">=</span> <span class="nx">that</span><span class="p">.</span><span class="nx">toString</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">toString</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">super_toString</span><span class="p">()</span><span class="o">+</span><span class="s2">" Despacho:"</span><span class="o">+</span><span class="nx">_despacho</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="nx">toString</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">that</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Como se puede ver en el código, no se manipulan los prototipos para crear la relación de herencia. Hay que recordar que cuandos se usan módulos, no se utilizan los prototipos para nada. Todos los objetos están asociados al prototipo <code>Object.prototype</code>. Es decir, el objeto creado con esta técnica tendrá como propiedades todos los atributos y métodos.</p>
<p>Otro detalle que es importante notar es la llamada al método redefinido <code>toString</code>:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">super_toString</span> <span class="o">=</span> <span class="nx">that</span><span class="p">.</span><span class="nx">toString</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">toString</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">super_toString</span><span class="p">()</span><span class="o">+</span><span class="s2">" Despacho:"</span><span class="o">+</span><span class="nx">_despacho</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Primero se guarda una referencia al método <code>toString</code> de la clase padre de forma que pueda usarse durante las posteriores ejecuciones del método redefinido.</p>
<p>Para crear un objeto jefe y usar sus métodos:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">jefe</span> <span class="o">=</span> <span class="nx">newJefe</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">,</span> <span class="mi">700</span><span class="p">,</span> <span class="s2">"E12"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">jefe</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<h2>Herencia con clases con librerías en JavaScript</h2>
<p>Las librerías de definición de clases muestran su verdadero potencial al crear jerarquías de herencia de clases. Cabe recordar que la mayoría de ellas facilitan la creación de clases como prototipos.</p>
<p>Las principales funcionalidades que ofrecen son:
* Azucar sintáctico para crear clases visualmente más parecidas a lenguajes como Java.
* Automatizan la configuración del objeto prototipo de la clase hija como una instancia de la clase padre.
* Automatizan la invocación del constructor de la clase padre antes de invocar el constructor de la clase hija.
* Ofrecen mecanismos sencillos para llamar a métodos redefinidos de la clase padre.</p>
<h3>Prototype.js</h3>
<p>Para crear una jerarquía de herencia con Prototype.js se utiliza el siguiente patrón:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">Empleado</span> <span class="o">=</span> <span class="nx">Class</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getNombre</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getSalario</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="kd">var</span> <span class="nx">Jefe</span> <span class="o">=</span> <span class="nx">Class</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">Empleado</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$super</span><span class="p">,</span> <span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">,</span> <span class="nx">despacho</span><span class="p">){</span>
<span class="nx">$super</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="nx">despacho</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$super</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">$super</span><span class="p">()</span> <span class="o">+</span> <span class="s2">" Despacho:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">despacho</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div>
<p>Como se puede apreciar, el código es bastante más limpio que crear directamente la clase hija usando cualquiera de los patrones anteriores. Una de las principales ventajas de usar esta librería es el atributo <code>$super</code> utilizado para acceder al constructor y a los métodos redefinidos de la clase padre.</p>
<h3>JS.Class</h3>
<p>En el caso de JS.Class la creación de una jerarquía de herencia es muy parecida a Prototype.JS:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">Empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Class</span><span class="p">({</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getNombre</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">getSalario</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">salario</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="s2">"Nombre:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="o">+</span><span class="s2">", Salario:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="kd">var</span> <span class="nx">Jefe</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Class</span><span class="p">(</span><span class="nx">Empleado</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">,</span> <span class="nx">despacho</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">callSuper</span><span class="p">(</span><span class="nx">nombre</span><span class="p">,</span> <span class="nx">salario</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="nx">despacho</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">toString</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">callSuper</span><span class="p">()</span> <span class="o">+</span> <span class="s2">" Despacho:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">despacho</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div>
<p>En este caso, el parámetro <code>$super</code> se sustituye por un método <code>callSuper</code> en el objeto que está accesible durante la ejecución de los métodos de la clase hija.</p>
<h1>Manipulación de clases y objetos</h1>
<p>Cuando se utiliza la programación orientada a objetos, la mayor parte del código de un programa consiste en definir clases, crear objetos e invocar sus métodos. No obstante, también hay una serie de servicios adicionales relacionados con las clases y los objetos que también se utilizan en un lenguaje. A continuación se muestra cómo se ven afectados esos servicios adicionales cuando se usa un patrón u otro.</p>
<h2>Métodos como funciones independientes</h2>
<p>En los lenguajes funcionales como JavaScript y Java 8 es bastante habitual tratar los métodos de un objeto como funciones independientes que se pasan a otras funciones. Por ejemplo, supongamos que usamos una librería en la que tenemos que establecer un <em>callback</em>, es decir, una función que será llamada cuando se produzca un determinado evento.</p>
<div class="highlight"><pre><code class="javascript"><span class="nx">lib</span><span class="p">.</span><span class="nx">addCallback</span><span class="p">(</span><span class="nx">func</span><span class="p">);</span>
</code></pre></div>
<p>Si queremos pasar un método de un objeto como callback hemos de tener en cuenta el patrón elegido para implementar las clases porque esto afecta a cómo se debe pasar el método a la función.</p>
<p>Si hemos usado el patrón de clases con módulos podemos usar el método directamente como callback:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="nx">newEmpleado</span><span class="p">(</span><span class="s2">"Antonio"</span><span class="p">,</span> <span class="mi">500</span><span class="p">);</span>
<span class="nx">lib</span><span class="p">.</span><span class="nx">addCallback</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span> <span class="p">);</span>
</code></pre></div>
<p>En cambio, si hemos usado el patrón de clases con prototipos o clases con librerías, no podemos usar este enfoque. Esto se debe a que cuando se invoca un método como una función independiente la variable implícita <code>this</code> no está asociada al objeto original. En este caso, tendríamos que usar el siguiente esquema:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">(</span><span class="s2">"Antonio"</span><span class="p">,</span> <span class="mi">500</span><span class="p">);</span>
<span class="nx">lib</span><span class="p">.</span><span class="nx">addCallback</span><span class="p">(</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">toString</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">empleado</span><span class="p">)</span> <span class="p">);</span>
</code></pre></div>
<p>Es bastante parecido, pero hay que tener en cuenta la sutil diferencia.</p>
<p>En Java 8 también se puede pasar un método como parámetro cuando se espera una función de la siguiente forma:</p>
<div class="highlight"><pre><code class="java"><span class="n">Empleado</span> <span class="n">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Empleado</span><span class="o">(</span><span class="s">"Antonio"</span><span class="o">,</span> <span class="mi">500</span><span class="o">);</span>
<span class="n">lib</span><span class="o">.</span><span class="na">addCallback</span><span class="o">(</span> <span class="nl">empleado:</span><span class="o">:</span><span class="n">toString</span> <span class="o">);</span>
</code></pre></div>
<h2>Reflexión</h2>
<p>La reflexión es un aspecto importante de un lenguaje de programación. Aunque no tengo mucha experiencia con lenguajes dinámicos, creo que la reflexión se utiliza mucho más en este tipo de lenguajes que en los lenguajes con tipado estático. Creo que eso se debe a que en los lenguajes con tipado estático la reflexión es más costosa que el uso directo de los elementos del lenguaje. En cambio, en los lenguajes dinámicos, la diferencia es menor. Además, en los lenguajes dinámicos la flexibilidad se explota mucho más que en los lenguajes con tipado estático.</p>
<p>En JavaScript existen diversos mecanismos para programar de forma reflexiva con la orientación a objetos, pero depende del patrón que se haya usado se podrán usar de una forma u otra. A continuación se describe cada uno de ellos:</p>
<h3>Saber si un valor es un objeto</h3>
<p>En Java el sistema de tipos está dividido en dos: tipos primitivos y objetos. Para saber si un objeto es realmente un objeto o un array, se puede usar el siguiente esquema:</p>
<div class="highlight"><pre><code class="java"><span class="k">if</span><span class="o">(</span><span class="n">obj</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">isArray</span><span class="o">())</span> <span class="o">{</span>
<span class="c1">//Es array</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
<span class="c1">//Es objeto no array</span>
<span class="o">}</span>
</code></pre></div>
<p>En JavaScript el operador <code>typeof</code> es un operador infijo que devuelve el tipo de un valor como un string. Cuando el valor es un objeto o un array, este operador devuelve <code>'object'</code>. Por ejemplo, para saber si un valor es un objeto o un array se usa el siguiente esquema:</p>
<div class="highlight"><pre><code class="javascript">
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">variable</span> <span class="o">===</span> <span class="s1">'object'</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">variable</span><span class="p">){</span>
<span class="c1">//Es array</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">//Es objeto no array</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>Esta técnica se puede usar con cualquiera de los patrones. Se puede consultar esta página <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof">para más información sobre el operador typeof</a> y la función <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray">isArray</a>.</p>
<h3>Saber la clase de un objeto</h3>
<p>El operador infijo <code>instanceof</code> se usa para saber la clase de un objeto cuando se usa el patrón de clase como prototipo. Se utiliza comparando el objeto con la función constructora siguiendo el siguiente esquema:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">esJefe</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Jefe</span><span class="p">;</span> <span class="c1">// true</span>
<span class="kd">var</span> <span class="nx">esEmpleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Empleado</span><span class="p">;</span> <span class="c1">// true</span>
<span class="kd">var</span> <span class="nx">esRectangulo</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Rectangulo</span><span class="p">;</span> <span class="c1">// false</span>
</code></pre></div>
<p>Conceptualmente es similar al operador <code>instanceof</code> en Java. Además usa la misma sintáxis:</p>
<div class="highlight"><pre><code class="java"> <span class="kt">boolean</span> <span class="n">esJefe</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Jefe</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">Jefe</span><span class="o">;</span> <span class="c1">// true</span>
<span class="kt">boolean</span> <span class="n">esEmpleado</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Jefe</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">Empleado</span><span class="o">;</span> <span class="c1">// true</span>
<span class="kt">boolean</span> <span class="n">esRectangulo</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Jefe</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">Rectangulo</span><span class="o">;</span> <span class="c1">// false</span>
</code></pre></div>
<p>Hay que tener en cuenta que este operador no se puede usar con el patrón de clases con módulos. Esto se debe a que los objetos creados de esa forma son únicamente de la clase Object (ya que están asociados al prototipo <code>Object.prototype</code>).</p>
<h3>Acceso a la clase de un objeto</h3>
<p>Para acceder a la clase de un objeto en Java se usa el método <code>getClass()</code>:</p>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Empleado</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">();</span>
<span class="nx">Class</span> <span class="nx">clase</span> <span class="o">=</span> <span class="nx">empleado</span><span class="p">.</span><span class="nx">getClass</span><span class="p">();</span>
<span class="nx">clase</span><span class="p">.</span><span class="nx">isInstance</span><span class="p">(</span><span class="nx">empleado</span><span class="p">);</span> <span class="c1">//true</span>
</code></pre></div>
<p>Cuando se usa el patrón de clases con prototipos, la clase está representada como el prototipo. En ese caso se puede consultar el prototipo de un objeto usando el método <code>getPrototypeOf</code> con el siguiente esquema:</p>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">prototipo</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getPrototypeOf</span><span class="p">(</span><span class="nx">empleado</span><span class="p">);</span>
<span class="nx">prototipo</span> <span class="o">==</span> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span> <span class="c1">// true</span>
</code></pre></div>
<p>El método <code>getPrototypeOf()</code> se ha incorporado hace poco a JavaScript, pero desde hace tiempo existe una propiedad llamada <code>__proto__</code> que guarda una referencia al prototipo. Aunque en funcion en algunos casos, es mejor usar el estándar. No obstante, cuando estamos inspeccionando un objeto en el depurador, esa propiedad suele estar presente y apunta al objeto prototipo.</p>
<p>Al igual que ocurre con el operador <code>instanceof</code>, el método <code>getPrototypeOf</code> tampoco se puede usar con el patrón de clases como módulo porque el prototipo siempre es <code>Object.prototype</code>.</p>
<p>Es decir, no podemos usar ningún mecanismo del lenguaje para conocer de forma reflexiva la clase de un objeto si usamos el patrón de clase con módulo. Como forma de solucionar el problema, siempre se podría usar un atributo que guardara el nombre de la clase, pero no sería una técnica nativa del lenguaje.</p>
<h3>Acceso a las propiedades de un objeto</h3>
<p>En Java se puede acceder a los atributos de un objeto de la siguiente forma:</p>
<div class="highlight"><pre><code class="java"> <span class="k">for</span><span class="o">(</span><span class="n">Field</span> <span class="n">field</span> <span class="o">:</span> <span class="n">objeto</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">getFields</span><span class="o">()){</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span> <span class="n">field</span><span class="o">.</span><span class="na">getName</span><span class="o">()+</span><span class="s">": "</span><span class="o">+</span> <span class="n">field</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">objeto</span><span class="o">));</span>
<span class="o">}</span>
</code></pre></div>
<p>Y a los métodos:</p>
<div class="highlight"><pre><code class="java"> <span class="k">for</span><span class="o">(</span><span class="n">Method</span> <span class="n">method</span> <span class="o">:</span> <span class="n">objeto</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">getMethods</span><span class="o">()){</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span> <span class="n">method</span><span class="o">.</span><span class="na">getName</span><span class="o">()+</span><span class="s">": "</span><span class="o">+</span> <span class="n">method</span><span class="o">.</span><span class="na">toGenericString</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div>
<p>En JavaScript se puede recorrer la lista de propiedades de un objeto (atributos y métodos) con el siguiente esquema:</p>
<div class="highlight"><pre><code class="javascript"> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">objeto</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">propiedad</span><span class="o">+</span><span class="s2">": "</span><span class="o">+</span><span class="nx">objeto</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div>
<p>Usando typeof se puede acceder sólo a los atributos, no a los métodos.</p>
<div class="highlight"><pre><code class="javascript"> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">objeto</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">valorPropiedad</span> <span class="o">=</span> <span class="nx">objeto</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">valorPropiedad</span> <span class="o">!==</span> <span class="s1">'function'</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">propiedad</span><span class="o">+</span><span class="s2">": "</span><span class="o">+</span><span class="nx">valorPropiedad</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>Cuando se usa el patrón de clases con prototipos, se puede determinar si un método es de la clase hija o de cualquiera de las clases padre:</p>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">prototipo</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getPrototypeOf</span><span class="p">(</span><span class="nx">objeto</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">prototipo</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">prototipo</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">]</span> <span class="o">===</span> <span class="s1">'function'</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">prototipo</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">propiedad</span><span class="p">))</span>
<span class="c1">//El método propiedad está en la clase hija</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">//El método propiedad está en alguna de las clases padre</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>Usando el patrón de clases con prototipos no se puede determinar si los atributos son de la clase hija o de la clase padre porque todos los atributos son propiedades del objeto.</p>
<p>Cuando se usa el patrón de clases con módulos no se puede determinar si los atributos o métodos están en la clase hija o en alguna de las clases padre porque todos los atributos y métodos son propiedades del objeto.</p>
<h2>Depuración</h2>
<p>La depuración o ejecución paso a paso es una técnica muy útil en el desarrollo de programas. Sobre todo se utiliza para comprender el funcionamiento de un programa que se comporta de forma errónea. Aunque las técnicas de desarrollo <em>Test Driven Development</em> han reducido la necesidad de utilizar la depuración, todavía sigue siendo una herramienta muy útil en manos del desarrollador.</p>
<p>A la hora de elegir una técnica de implementación de clases en JavaScript es importante tener en cuenta el impacto que tiene la técnica elegida en el depurador. Cuando se implementan las clases como prototipos, los atributos de los objetos son propiedades del objeto y se pueden visualizar en el depurador. En cambio, cuando se usa la técnica de clases con módulos, como los atributos son variables en la closure de los métodos, esos atributos no se muestran en el depurador a no ser que estemos parados en un método que hace uso de esas variables.</p>
<h1>Conclusión ¿Qué patrón usar?</h1>
<p>Después de este repaso por la orientación a objetos en JavaScript tenemos que elegir qué patron usar de los tres disponibles:</p>
<ul>
<li>Clases con prototipos</li>
<li>Clases con prototipos con librerías</li>
<li>Clases con módulos</li>
</ul>
<p>Aunque el uso de las librerías puede simplificar el código, algunos desarrolladres experimentados en JavaScript me dicen que actualmente (principios del 2014) no es una buena práctica en JavaScript definir jerarquías de clases usando estas librerías. Pero no tengo claro el motivo. No sé si están en contra de las librerías o del uso de los prototipos.</p>
<p>El autor de <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The Good Parts</a> dice en <a href="http://javascript.crockford.com/inheritance.html">un post</a> que intentar simular las jerarquías de herencia clásicas en JavaScript fue un error para él porque JavaScript tiene otros mecanismos de reutilización de código. Parece que está en contra de los artificios de las librerías por implementar el concepto de <code>super</code>, pero no entiendo muy bien su argumentación. No sé si está en contra de las librerías o del uso de los prototipos.</p>
<p>En esta respuesta a la pregunta <a href="http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript#1598077">How to properly create a custom object in javascript</a> en StackOverlow su autor dice que no hay consenso sobre cual es mejor.</p>
<blockquote><p>Which way is “proper”? Both. Which is “best”? That depends on your situation. FWIW I tend towards prototyping for real JavaScript inheritance when I'm doing strongly OO stuff, and closures for simple throwaway page effects.</p>
<p>But both ways are quite counter-intuitive to most programmers. Both have many potential messy variations. You will meet both (as well as many in-between and generally broken schemes) if you use other people's code/libraries. There is no one generally-accepted answer. Welcome to the wonderful world of JavaScript objects.</p></blockquote>
<p>Además, hay que tener en cuenta las ventajas e inconvenientes de cada patrón. Hagamos un resumen de cada uno de ellos:</p>
<h3>Clases con prototipos</h3>
<ul>
<li><strong>Ventajas:</strong> Es la forma nativa de implementar clases en JavaScript. Tiene mejor soporte de las herramientas de reflexión y depuración del lenguaje. Además, habrá más desarrolladores que comprendan el código, por tanto será más fácil compartir el código, corregir errores, etc. También es posible que esté más optimizado en los motores de JavaScript.</li>
<li><strong>Inconvenientes:</strong> La sintáxis es verbosa y propensa a errors. No hay encapsulación en atributos ni métodos.</li>
</ul>
<h3>Clases con prototipos con librerías</h3>
<ul>
<li><strong>Ventajas:</strong> El código es más limpio. Es más fácil de entender por desarrolladores que tengan experiencia en prácticamente cualquier lenguaje de programacíón del planeta menos JavaScript, es decir, aquellos que tienen programación orientada a objetos con clases, no con prototipos. Es un azucar sintáctico para crear clases con prototipos, así que todas las ventajas de los prototipos también se tienen aquí. Incluso algunas librerías tiene su propia librería de reflexión.</li>
<li><strong>Desventajas:</strong> Parece ser que usar estas librerías es <em>old school</em> y no mola. No sé muy bien el motivo todavía. Depender de una librería con muchas funcionalidades sólo por la parte de creación de clases puede ser demasiado costoso, aunque hay librerías que se dedican exclusivamente a esto y son muy pequeñas. Como hay tropecientas librerías, hay una alta probabilidad de que la que tu elijas sólo la conozcas tu, obligando a los desarrolladores que quieran colaborar contigo a aprender una nueva librería por cada proyecto.</li>
</ul>
<h3>Clases con módulos</h3>
<ul>
<li><strong>Ventajas:</strong> Tenemos bastante más encapsulación que con el patrón de prototipos. Todavía cualquiera puede cambiar los métodos de un objeto (consiguiendo el mismo efecto que modificando el valor de atributos privados), pero es más complicado de hacer por equivocación. También estamos menos expuestos al problema de que se olvide usar <code>new</code> para crear un objeto y a que se olvide hacer el <code>bind</code> cuando usamos los métodos como funciones independientes.</li>
<li><strong>Inconvenientes:</strong> No tenemos soporte de reflexión con las librerías del lenguaje. Puede haber un impacto en el consumo de memoria importante porque todos los objetos tienen todos los métodos. Los desarrolladores del lenguaje Ceylon (que compila a JavaScript) indican que <a href="http://ceylon-lang.org/blog/2012/01/02/prototypes-ceylon-js/">las clases con módulos pueden llegar a ser hasta 100 veces más lentas que las clases como prototipos</a> en la máquina virtual V8. Y por último, el soporte del depurador es bastante más limitado con este patrón.</li>
</ul>
<p>Entonces, ¿Qué hago? ¿Qué patron utilizo? La verdad es que no lo tengo claro.</p>
<p>¿Me puedes decir que opción usas tu y por qué lo haces en los comentarios? Seguro que me ayudas a elegir y a muchos que tienen las mismas dudas que yo.</p>
<div id="note">
<p>Este post forma parte de una de una serie de posts en los que cuento mi viaje por las tecnologías de front-end, esas que permiten implementar aplicaciones web interactivas. Todo ello desde el punto de vista de un programador Java con más de 10 años de experiencia. Si te interesa puedes echar un vistazo a las demás entradas:</p>
<ul>
<li>Parte 1: <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Viaje por las tecnologias de front end</a></li>
<li>Parte 2: <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Primer contacto con JavaScript</a>,</li>
<li>Parte 3: <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">Orientacion a Objetos en JavaScript comparado con Java</a></li>
<li>Parte 4: <a href="/blog/JavaScript-no-es-orientado-a-objetos">JavaScript no es orientado a objetos</a></li>
</ul>
</div>
Primer contacto con JavaScript. Tecnologías Front-end (Parte 2)2013-12-27T00:00:00-08:00http://micaelgallego.github.com/blog/Viaje-por-las-tecnologias-de-front-end2<p>Esta entrada es la segunda parte de mi "Viaje por las tecnologías de "front-end". Si no lo has leído, te recomiendo que eches un vistazo al <a href="http://micaelgallego.github.io/blog/Viaje-por-las-tecnologias-de-front-end/">primer post</a> en el que cuento cual es mi roadmap, qué tecnologías tengo pensado estudiar y por qué.</p>
<p>Aunque he estado viendo algunas cosillas de HTML y CSS, todavía me queda darle un empujón a esa parte. Con lo que más he avanzado ha sido con JavaScript. Recomendado por <a href="http://www.linkedin.com/pub/anthanh-pham-trinh/38/502/b05">Anthanh</a> me he leído el libro de <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">JavaScript: The good parts</a>. También he consultado algunas páginas oficiales de Mozilla y un par de preguntas en StackOverflow. A medida que vaya poniendo las notas de JavaScript pondré los links que he mirado.</p>
<p><a href="https://twitter.com/jllado">Juan Llado</a> me ha recomendado el libro <a href="http://www.manning.com/resig/">Secrets of the Javascript Ninja</a> del creador de jQuery. Todavía no le he echado un vistazo, pero seguro que es bastante completo.</p>
<p>He decidido poner las conclusiones al principio, para que sepas lo que pienso de JavaScript después de mi primer contacto.</p>
<p>Después viene un resumen de lo que he aprendido del lenguaje en los dos últimos días. He hecho el resumen asumiendo que el lector conoce Java (como en mi caso). De forma que sea rápido para un desarrollador de Java saber qué es igual y qué es diferente.</p>
<p>Si controlas de JavaScript y ves alguna concepto mal explicado o erróneo. Ponme un comentario y me ayudarás a aprender. Si no tienes ni idea de JavaScript (como yo), a lo mejor te sirve de guía de aprendizaje ;)</p>
<h1>Conclusiones</h1>
<h2>El libro "JavaScript: The Good Parts"</h2>
<ul>
<li>Es consiso y se centra en las buenas partes del lenguaje, pero bajo mi punto de vista está un poco desorganizado. Sobre todo para los que venimos de Java. Algunas cosas que me han parecido confusas o desorganizadas:
<ul>
<li>Cuenta los bloques try / catch junto con el resto de sentencias de control de flujo. Yo hablaría de excepciones en un tema aparte.</li>
<li>Describe aspectos propios de la reflexión cuando te está contando cómo son las funciones y los objetos. Supongo que en JavaScript es normal tratar los elementos de forma reflexiva por la naturaleza dinámica del lenguaje, pero los que venimos de un lenguaje con tipado estático normalmente usamos la reflexión "con cuidado".</li>
<li>La forma de explicar la orientación a objetos es un poco confusa, porque te explica varias formas de crear clases y objetos pero no concreta en cual es la mejor forma de hacerlo. Además, lo cuenta en diferentes partes del libro, cuando hubiera sido mejor agruparlo.</li>
<li>La explicación del patrón módulo me parece un poco confusa porque no lo relaciona con el concepto de clase al principio.</li>
<li>Te describe idiomas de programación a la misma vez que te explica el lenguaje como "cascade" (fluent API) o memoization (variables de función que se inicializan la primera vez).</li>
</ul>
</li>
</ul>
<h2>Futuros pasos con el lenguaje</h2>
<ul>
<li>Creo que finalmente he conseguido enterarme de los conceptos básicos del lenguaje. Aunque todavía me falta mirarme más material antes de que pueda sentirme agusto con "el lenguaje" y los patrones básicos. En concreto:
<ul>
<li><a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/">Patrones de diseño en JavaScript</a></li>
<li><a href="http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html">Patrón módulo</a></li>
<li>Librería <a href="http://jquery.com/">jQuery</a></li>
<li>Librería <a href="http://underscorejs.org/">Underscore.js</a></li>
</ul>
</li>
</ul>
<h2>¿Qué pienso de JavaScript?</h2>
<ul>
<li>Todo lo que pensaba del lenguaje antes de aprender JavaScript lo sigo manteniendo: JavaScript es un mal lenguaje.</li>
<li>A mi no me gustan mucho los lenguajes con tipado dinámico, porque me gusta que el compilador me ayude lo más posible cuando me equivoco y me gustan las ayudas de los IDEs. Pero he usado otros lenguajes con tipado dinámico como Ruby y un poco Python y me parece que su modelo de orientación a objetos es muy razonable (muy similar a Java). No entiendo por qué JavaScript utilizó la programación orientada a objetos basada en prototipos.</li>
<li>Por lo que sé hasta ahora no hay consenso con la forma adecuada de representar los objetos. Mejor copiar todo en el objeto final? Mejor usar prototipos? Mejor usar ámbitos de funciones? La falta de un consenso y una forma aceptada de hacer bien las cosas creo que es negativa en un lenguaje.</li>
<li>El patrón módulo permite modularizar el programa y evitar colisiones en el objeto global, pero he encontrado poco soporte en las herramientas de depuración para este patrón. Por ejemplo, ¿Cómo puedo ver el contexto de una función sin estar parado en una sentencia suya en el depurador?</li>
<li>Cuando más aprendo JavaScript más me acuerdo de lo bueno que es tener una especificación formal del lenguaje en Java y un runtime certificado (la JVM). Buscar información sobre JavaScript en Internet es una odisea. No paro de econtrar frases como: "esto no se puede en este navegador (pero si en los demás)", "esto si se puede en la gran mayoría (pero no es estándar)", etc... Pasa lo mismo que en SQL.</li>
<li>El lenguaje tiene errores de diseño garrafales. Algunos son fáciles de solventar (no usando la funcionalidad maligna), pero otros están enraizados en el propio lenguaje.</li>
</ul>
<h2>Las conclusiones de las conclusiones</h2>
<ul>
<li>En definitiva, JavaScript es un mal lenguaje, pero no hay más remedio que usarlo porque es la plataforma más extendida del planeta. El creador del lenguaje tampoco tiene la culpa, supongo que nunca pensó que llegaría tan lejos.</li>
<li>Supongo que cuando controle un poco de JavaScript tendré que mirar CoffeeScript o Dart, aunque no tengo claro si merece la pena otro nivel de indirección más ;).</li>
</ul>
<h1>Sintaxis básica</h1>
<ul>
<li>La sintaxis básica está inspirada en Java y C.</li>
<li>Tiene recolector de basura como Java.</li>
</ul>
<h2>Mostrar información por pantalla</h2>
<ul>
<li>document.write('Texto'): Escribe en el documento HTML.</li>
<li>console.log('Texto'): Escribe en la consola JavaScript.</li>
</ul>
<h2>Ejecución</h2>
<ul>
<li>Documento .html que enlaza al código .js</li>
</ul>
<div class="highlight"><pre><code class="html"> <span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><link</span> <span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">href=</span><span class="s">"/js/script.js"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div>
<ul>
<li>Fichero .js que contiene el código</li>
</ul>
<h2>Comentarios</h2>
<ul>
<li>Como en Java (una línea y multilínea)</li>
<li>Se recomienda usar el de única porque no se puede comentar algunos tipos de expresiones regulares con el multilínea</li>
</ul>
<h2>Palabras reservadas</h2>
<ul>
<li>abstract</li>
<li>boolean break byte</li>
<li>case catch char class const continue</li>
<li>debugger default delete do double</li>
<li>else enum export extends</li>
<li>false final finally float for function</li>
<li>goto</li>
<li>if implements import in instanceof int interface</li>
<li>long</li>
<li>native new null</li>
<li>package private protected public</li>
<li>return</li>
<li>short static super switch synchronized</li>
<li>this throw throws transient true try typeof</li>
<li>var volatile void</li>
<li>while with</li>
</ul>
<h2>Delimitadores</h2>
<ul>
<li>Se usan {} y ; como en Java</li>
</ul>
<h2>Tipos de datos</h2>
<ul>
<li>Todos los valores son objetos. No existe la distinción entre tipos primitivos y objetos que hay en Java.</li>
<li>Los tipos de datos básicos son: number, string, boolean</li>
</ul>
<h3>Tipo Number</h3>
<ul>
<li>Números enteros y reales de cualquier precisión.</li>
<li>Literal (como en Java pero sin notación octal o hexadecimal)</li>
<li>Inmutable (como en Java)</li>
<li>El valor NaN se usa cuando no se puede realizar una operación (como en Java)</li>
</ul>
<h3>Tipo string</h3>
<ul>
<li>Entre comillas simples o comillas dobles</li>
<li>Como no hay tipo caracter, se usan strings con un caracter.</li>
<li>Propiedad .length (como en Java)</li>
<li>Operador + (como en Java)</li>
<li>Inmutables (como en Java)</li>
<li>Caracteres especiales y unicode (como en Java)</li>
</ul>
<h3>Tipo boolean</h3>
<ul>
<li>boolean: true o false.</li>
<li>Inmutable (como en Java)</li>
</ul>
<h2>Variables</h2>
<ul>
<li>Es un lenguaje con tipado dinámico</li>
<li>Las variables se tienen que declarar pero no se indica el tipo. Se infiere del valor asignado</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//La variable edad tendrá un valor de 34</span>
<span class="kd">var</span> <span class="nx">edad</span> <span class="o">=</span> <span class="mi">34</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">encontrado</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>Las declaraciones se suelen hacer al principio de la función.</li>
<li>La variable tiene como ámbito la función, no el bloque. Al finalizar el bloque, la variable sigue presente (En Java es por bloque).</li>
<li>Regla de estilo: empieza minúsculas y separa con _ (en Java se separa con Mayúsculas).</li>
<li>Si no se inicializan, las variables tienen el valor <code>undefined</code> (no <code>null</code>)</li>
<li>No existe final para declarar constantes</li>
</ul>
<h2>Operadores en expresiones</h2>
<ul>
<li>Similares a Java
<ul>
<li>Aritméticos: + - * / % (a división es siempre real)</li>
<li>Comparación números: < > <= >=</li>
<li>Lógicos: && || !</li>
<li>Comparativo: ?: (Elvis operator)</li>
<li>Modificación: ++ --</li>
<li>Asignación: = += -= *= /= %=</li>
</ul>
</li>
<li>Diferentes a Java
<ul>
<li>Comparación:
<ul>
<li>Igual: ===</li>
<li>Distinto: !==</li>
<li>En strings se comporta como equals en Java</li>
<li>En arrays se comporta como == en Java</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Tratamiento de valores undefined</h2>
<ul>
<li>Si una expresión se evalúe como undefined se puede usar el operador || para devolver otro valor:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">fligth</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">status</span> <span class="o">=</span> <span class="nx">flight</span><span class="p">.</span><span class="nx">status</span> <span class="o">||</span> <span class="s2">"unknown"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">status</span><span class="p">);</span> <span class="c1">//Imprime "unknown"</span>
</code></pre></div>
<ul>
<li>Si queremos acceder a un atributo que puede no estar definido (lo que provocaría un TypeError) se puede usar el operador && para acceder sólo si existe:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">fligth</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="kr">char</span> <span class="o">=</span> <span class="nx">flight</span><span class="p">.</span><span class="nx">status</span> <span class="o">&&</span> <span class="nx">flight</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="kr">char</span><span class="p">);</span> <span class="c1">//Imprime "undefined"</span>
</code></pre></div>
<ul>
<li>Se tiene este comportamiento porque los operadores lógicos en realidad se definen así:
<ul>
<li>Operador OR ||: Devuelve el primer operando si no tiene un valor que se interprete como falso. En otro caso devuelve el segundo operando. Como undefined se interpreta como falso, se devuelve el segundo operando en caso de que el primero evalúe como undefined. Hay que tener cuidado porque 0 y "" también se interpretan como falso.</li>
<li>Operador AND &&: Devuelve el primer operando si tiene un valor que se interprete como falso. En otro caso devuelve el segundo operando. Como undefined se interpreta como falso, se devuelve undefined en caso de que el primero evalúe como undefined. Hay que tener cuidado porque 0 y "" también se interpretan como falso.</li>
</ul>
</li>
</ul>
<h1>Arrays</h1>
<h2>Igual que en Java</h2>
<ul>
<li>El acceso para lectura o escritura es con [ ]</li>
<li>Tienen la propiedad length</li>
<li>Empiezan por 0</li>
<li>La asignación no copia, las variables apuntan al mismo objeto</li>
<li>El operador === compara si son el mismo objeto (no el mismo contenido)</li>
<li>Los arrays de varias dimensiones son arrays de arrays. Hay que crear de forma explícita los niveles.</li>
</ul>
<h2>Diferente a Java</h2>
<ul>
<li>Los literales son con [ ] en vez de { }</li>
<li>No se pone new en el literal</li>
</ul>
<div class="highlight"><pre><code class="javascript"><span class="kd">var</span> <span class="nx">empty</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">var</span> <span class="nx">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'zero'</span><span class="p">,</span><span class="s1">'one'</span><span class="p">,</span><span class="s1">'two'</span><span class="p">,</span><span class="s1">'three'</span><span class="p">]</span>
</code></pre></div>
<ul>
<li> Los arrays pueden mezclar valores de varios tipos.</li>
</ul>
<h2>Errores de acceso</h2>
<ul>
<li>El acceso a un elemento fuera de los límites es <code>undefined</code></li>
<li>El intento de acceso a un array undefined da un error <code>TypeError</code></li>
</ul>
<h2>Gestión como listas</h2>
<ul>
<li>Se pueden establecer elementos en posiciones no existentes y el array crece dinámicamente.</li>
<li>El método push es igual que add en Java.</li>
<li>La propiedad length se puede cambiar para reducir el tamaño del array.</li>
<li>El operador delete borra un elemento (pero deja el hueco)</li>
</ul>
<div class="highlight"><pre><code class="javascript"><span class="k">delete</span> <span class="nx">numbers</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</code></pre></div>
<ul>
<li>Para borrar y no dejar el hueco se usa el método splice indicando el índice desde el que hay que borrar y el número de elementos.</li>
</ul>
<div class="highlight"><pre><code class="javascript"><span class="nx">numbers</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</code></pre></div>
<h1>Sentencias de control de flujo</h1>
<h2>Bloque de sentencias</h2>
<ul>
<li>Con { } como en Java</li>
<li>Las variables no desaparecen al terminar el bloque (diferente a Java).</li>
</ul>
<h2>Sentencia if</h2>
<ul>
<li>Sintaxis como en Java</li>
<li>La expresión no tiene que ser booleana</li>
<li>Se interpreta como falso:
<ul>
<li>false, null, undefined, '' (cadena vacía), 0, NaN</li>
</ul>
</li>
</ul>
<h2>Setencias switch, while y do</h2>
<ul>
<li>Sintaxis y semántica como en Java</li>
</ul>
<h2>Sentencia for</h2>
<ul>
<li>for(init; expr; inc) como en Java. La variable de control tiene que declararse fuera del bucle.</li>
<li>No tiene continue, pero si break como en Java.</li>
</ul>
<h2>Sentencias return y break</h2>
<ul>
<li>Como en Java.</li>
<li>Con soporte de etiquetas como en Java.</li>
</ul>
<h1>Funciones</h1>
<ul>
<li>JavaScript es un lenguaje funcional en el sentido de que las funciones son ciudadanos de primera clase en el lenguaje.</li>
<li>Se pueden declarar con un nombre:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">param</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">param</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="c1">// Imprime 4</span>
</code></pre></div>
<ul>
<li>También se pueden declarar funciones anónimas y asignarse a una variable. Posteriormente se usa el nombre de la variable para invocar la función:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">func</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">param</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">param</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">func</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="c1">// Imprime '4'</span>
</code></pre></div>
<ul>
<li>Las funciones son en realidad objetos, así que se pueden guardar en variables (como se ha visto en el ejemplo) o se pueden pasar como parámetros a otras funciones. En Java se puede obtener una funcionalidad similar con las clases anónimas o con los lambdas de Java 8.</li>
</ul>
<h2>Invocación de una función</h2>
<ul>
<li>Para invocar una función se indica su nombre seguido de una lista de expresiones entre paréntesis.</li>
<li>Normalmente se pasan tantas expresiones como parámetros se hayan declarado.</li>
<li>Si hay menos parámetros de los definidos en la cabecera de la función, los que faltan tendrán un valor undefined.</li>
<li>Si hay más valores, se ignoran (aunque se pueden obtener de forma reflectiva como se verá en la sección de reflexión).</li>
</ul>
<h2>Información accesible desde la función</h2>
<ul>
<li>Desde una función se tiene acceso a los parámetros y a las variables declaradas en dicha función.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">func</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">param</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">numero</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">param</span><span class="o">+</span><span class="s2">" numero:"</span><span class="o">+</span><span class="nx">numero</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">func</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="c1">// Imprime '4 numero:0'</span>
</code></pre></div>
<ul>
<li>También se tiene acceso a variables accesibles en el ámbito en el que se declara la función:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">texto</span> <span class="o">=</span> <span class="s2">"Hola"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">print_texto</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">texto</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">print_texto</span><span class="p">();</span> <span class="c1">// Imprime 'Hola'</span>
</code></pre></div>
<ul>
<li>Cuando se referencia a una variable no se accede a su valor en el momento de la declaración, si no a la propia variable en sí. El conjunto de variables a las que tiene acceso la función se llama cerradura o cierre (closure). Esto tiene algunos efectos como los siguientes:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">texto</span> <span class="o">=</span> <span class="s2">"Hola"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">print_texto</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">texto</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">print_texto</span><span class="p">();</span> <span class="c1">// Imprime 'Hola'</span>
<span class="nx">texto</span> <span class="o">=</span> <span class="s2">"Adios"</span><span class="p">;</span>
<span class="nx">print_texto</span><span class="p">();</span> <span class="c1">// Imprime 'Adios'</span>
</code></pre></div>
<ul>
<li>Las funciones se pueden declarar dentro de otras funciones:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">add_onclick_handler</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s2">"Alerta"</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>En Java, una clase anónima o una expresión lambda pueden acceder a las varibles accesibles en el ámbito sólo si las variables no cambian de valor. Esto se debe a que en Java se accede al valor, no a la variable. Y para evitar confusiones, el programador está obligado a que la variable no cambie de valor.</li>
<li>El acceso a las variables del contexto tiene que utilizarse con ciudado. En el siguiente ejemplo se puede ver un uso erróneo de una variable del contexto:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//La siguiente función asocia un gestor de eventos a cada </span>
<span class="c1">//uno de los nodos que muestra una alerta. La alerta debería </span>
<span class="c1">//mostrar el número de cada nodo, pero todas muestran el número total</span>
<span class="c1">//de nodos, que es el valor que toma la variable al final del bucle.</span>
<span class="kd">var</span> <span class="nx">add_onclick_handlers</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">nodes</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Para solucionar este problema, se podría intentar crear una variable local al cuerpo del for que tome el valor de la variable i. Pero también es errónea porque en JavaScript los bloques no definen el ámbito léxico de las variables. En Java este enfoque funciona porque el ámbito de las variables viene definido por los bloques.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//En realidad sólo existe una variable num para </span>
<span class="c1">//toda la función. </span>
<span class="kd">var</span> <span class="nx">add_onclick_handlers</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">num</span> <span class="o">=</span> <span class="nx">i</span><span class="p">;</span>
<span class="nx">nodes</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">num</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Para que cada nodo tenga su propio número de nodo es necesario crear un ámbito por cada nodo. Es decir, es necesario crear una función para capturar en un parámetro el valor de i en cada iteración. Luego ejecutamos dicha función y el valor devuelto es la función que realmente asociamos a la propiedad onclick del nodo:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">add_the_handlers</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">nodes</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}(</span><span class="nx">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<h1>Orientación a objetos</h1>
<ul>
<li>Los objetos se manejan mediante referencias como en Java</li>
<li>Asignación no copia el objeto, copia la referencia.</li>
<li>Comparación con === dice si son el mismo objeto, no si son iguales.</li>
<li>Crear un objeto nuevo (como en Java):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">persona</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
</code></pre></div>
<h2>Atributos</h2>
<ul>
<li>También se pueden crear objetos de forma literal con los atributos (y sus valores):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">persona</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">nombre</span> <span class="o">:</span> <span class="s2">"Pepe"</span><span class="p">,</span>
<span class="nx">apellido</span> <span class="o">:</span> <span class="s2">"García"</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Incluso se puede crear un objeto sin atributos usando la misma notación:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">persona</span> <span class="o">=</span> <span class="p">{};</span> <span class="c1">// Equivale a new Object();</span>
</code></pre></div>
<ul>
<li>Los atributos son accesible desde cualquier parte del programa (atributos públicos en Java).</li>
<li>Se accede a los atributos con la notación punto (como en Java):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">persona</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Juan"</span><span class="p">;</span>
</code></pre></div>
<ul>
<li><p>Si se intenta leer de un atributo que no existe se devuelve undefined (no hay error de ejecución).</p></li>
<li><p>A los objetos se les puede añadir atributos nuevos en tiempo de ejecución (en Java no se puede).</p></li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">persona</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">persona</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">persona</span><span class="p">.</span><span class="nx">apellido</span> <span class="o">=</span> <span class="s2">"García"</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>También se pueden quitar atributos en tiempo de ejecucion con el operador delete:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">delete</span> <span class="nx">persona</span><span class="p">.</span><span class="nx">apellido</span><span class="p">;</span>
</code></pre></div>
<h2>Métodos</h2>
<ul>
<li>Los métodos son funciones que se asocian a los objetos:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">persona</span><span class="p">.</span><span class="nx">nombre_completo</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">apellido</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>También se pueden asociar al crear el objeto con la notación literal:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">persona</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">nombre</span> <span class="o">:</span> <span class="s2">"Pepe"</span><span class="p">,</span>
<span class="nx">apellido</span> <span class="o">:</span> <span class="s2">"García"</span><span class="p">,</span>
<span class="nx">nombre_completo</span> <span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">apellido</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Para invocar un método de un objeto se usa la notación punto y los parámetros entre paréntesis (como en Java).</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">persona</span><span class="p">.</span><span class="nx">nombreCompleto</span><span class="p">()</span> <span class="p">);</span>
</code></pre></div>
<ul>
<li>Cuando una función se usa como un método (y se invoca con la notación punto) se puede usar la variable implícita this. Este variable apunta al objeto sobre el que se invoca el método (como en Java).</li>
<li>Como en los atributos, se pueden quitar métodos con el operador delete:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">delete</span> <span class="nx">persona</span><span class="p">.</span><span class="nx">nombre_completo</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>Como los tipos básicos y los arrays son objetos, también se pueden usar métodos en ellos:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kc">false</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// 'false'</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// '1,2,3'</span>
</code></pre></div>
<ul>
<li>Pero en los números no se puede usar la notación punto directamente:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="mi">2</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// genera SyntaxError</span>
</code></pre></div>
<ul>
<li>Hay que usar alguna de las formas:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="mi">2</span><span class="p">..</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// the second point is correctly recognized</span>
<span class="mi">2</span> <span class="p">.</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// note the space left to the dot</span>
<span class="p">(</span><span class="mi">2</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span> <span class="c1">// 2 is evaluated first</span>
</code></pre></div>
<ul>
<li>A los atributos y los métodos se les conoce como "propiedades" del objeto.</li>
</ul>
<h2>Clases como objetos prototipo</h2>
<ul>
<li>En JavaScript la programación orientada a objetos se puede está basada en prototipos. En Java está basada en el modelo "clásico" con clases.</li>
<li>En vez de tener una clase que define los atributos y métodos de los objetos de esa clase, se tiene un "objeto prototipo" al que se asocian otros objetos.</li>
<li>Por tanto, el concepto de clase en JavaScript se representa como un objeto que hace de prototipo de los demás objetos que se asocian a él.</li>
<li>Atributos:
<ul>
<li>Cuando se accede a un atributo en un objeto y no existe en dicho objeto, se busca en su prototipo y se devuelve su valor.</li>
<li>Cuando se escribe en un atributo, si no existe el atributo se crea en el objeto. Por tanto el valor se cambia en el objeto, no en el prototipo.</li>
</ul>
</li>
<li>Métodos:
<ul>
<li>Cuando se intenta ejecutar un método en un objeto y no existe en dicho objeto, se busca en su prototipo y se ejecuta.</li>
</ul>
</li>
<li>Aunque se pueden añadir atributos y métodos a cualquier objeto (al crear el objeto o en cualquier momento posterior), se usan prototipos para reducir la memoria usada por los objetos porque usan los métodos del prototipo. También se ahorra memoria porque los atributos son los del prototipo hasta que se escribe en ellos.</li>
<li>A un objeto se le pueden añadir y quitar atributos y métodos en tiempo de ejecución, pero no puede cambiar de clase (es decir, <a href="http://stackoverflow.com/questions/7015693/how-to-set-the-prototype-of-a-javascript-object-that-has-already-been-instantiat">no se puede cambiar el objeto prototipo</a>).</li>
<li>Los objetos pertenecen a una clase por el prototipo al que se asocian al crearse.</li>
<li>Los objetos creados con <code>new Object()</code> o con notación JSON se asocian al prototipo <code>Object.prototype</code>. Es como decir que son instancias de la clase Object.</li>
<li>Para asociar un objeto a un prototipo diferente de <code>Object.prototype</code> basta con crear una nueva función y llamarla con el operador <code>new</code>:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado</span><span class="p">(){};</span>
<span class="kd">var</span> <span class="nx">empleado1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">empleado2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">();</span>
</code></pre></div>
<ul>
<li>Una función diseñada para ser llamada con new se llama "constructor". Como regla de estilo se diferencia de las demás porque empieza por mayúsculas.</li>
<li>Es muy importante poner new antes de llamar al constructor. Si no se pone new, no se producirá ningún error al analizar el código ni tampoco en ejecución, pero el comportamiento obtenido será muy raro (se explicará más adelante).</li>
<li>Se puede acceder al objeto prototipo del constructor Empleado con:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>Se pueden añadir métodos y atributos a todos los empleados si se modifica el prototipo:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
</code></pre></div>
<ul>
<li>De esa forma, todos los empleados tendrán nombre y salario:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">empleado1</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span> <span class="c1">// Imprime 600</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">empleado2</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span> <span class="c1">// Imprime 600</span>
</code></pre></div>
<ul>
<li>Si cambiamos el salario a un empleado, el otro no se verá afectado:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">empleado1</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">700</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">empleado1</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span> <span class="c1">// Imprime 700</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">empleado2</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span> <span class="c1">// Imprime 600</span>
</code></pre></div>
<ul>
<li>También se pueden añadir métodos al prototipo:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Empleado</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">empleado1</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">empleado1</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span> <span class="c1">// Imprime Nombre:Pepe Salario:700</span>
</code></pre></div>
<ul>
<li>Pese a la naturaleza dinámica de JavaScript, si no se necesita añadir atributos y métodos en tiempo de ejecución, se puede especificar toda la clase junta:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado2</span><span class="p">()</span> <span class="p">{</span> <span class="p">};</span>
<span class="c1">//Atributos</span>
<span class="nx">Empleado2</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="nx">Empleado2</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
<span class="c1">//Métodos</span>
<span class="nx">Empleado2</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado2</span><span class="p">();</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
</code></pre></div>
<ul>
<li>Se puede usar también un constructor con parámetros (y usar this en el constructor):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado3</span><span class="p">(</span><span class="nx">nombre</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="nx">nombre</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//Atributos</span>
<span class="nx">Empleado3</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="nx">Empleado3</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
<span class="c1">//Métodos</span>
<span class="nx">Empleado3</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado3</span><span class="p">();</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
</code></pre></div>
<p> Pero en este caso, no tendría mucho sentido crear el atributo <code>nombre</code> en el prototipo, ya que todos los objetos de la clase empleado se crearían con el constructor y en este se crea un atributo por cada objeto.</p>
<ul>
<li><p>Como se ha visto, también se puede usar this en el constructor (como en Java).</p></li>
<li><p>Uno puede usar una sintaxis más compacta como la siguiente:</p></li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado4</span><span class="p">(){</span>
<span class="c1">//Atributos</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
<span class="c1">//Métodos</span>
<span class="k">this</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado4</span><span class="p">();</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
</code></pre></div>
<p> Pero en este caso, ni los atributos ni los métodos se asocian al prototipo, se asocian al nuevo objeto que se acaba de crear. Esto no es una mala práctica, simplemente conviene saber el impacto que puede tener en el consumo de memoria. El programador puede usar cualquiera de los enfoques.</p>
<ul>
<li>En algunos casos se puede usar el prototipo para los métodos y el objeto para los atributos:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//Atributos</span>
<span class="kd">function</span> <span class="nx">Empleado5</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Métodos</span>
<span class="nx">Empleado5</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">empleado</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado5</span><span class="p">();</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Pepe"</span><span class="p">;</span>
<span class="nx">empleado</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
</code></pre></div>
<ul>
<li>El problema con los enfoques vistos hasta ahora es los atributos de los objetos son públicos. Esa falta de encapsulación y abstracción puede hacer que nuestro código sea dificil de mantener porque haya otras partes del código que accedan directamente a los atributos.</li>
</ul>
<h2>Clases basadas en funciones</h2>
<ul>
<li>Para evitar los problemas de las clases basadas en prototipos se puede usar la técnica funcional. Con esta técnica, se utiliza la capacidad de las funciones de acceder a las variables que están en el ámbito en el que se declaran (se verá más en detalle después).</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">newEmpleado6</span><span class="p">(){</span>
<span class="c1">//Atributos</span>
<span class="kd">var</span> <span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Empleado genérico"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">salario</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</span>
<span class="c1">//Métodos</span>
<span class="kd">var</span> <span class="nx">println</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Nombre: "</span><span class="o">+</span><span class="nx">nombre</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Salario: "</span><span class="o">+</span><span class="nx">salario</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">set_nombre</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">_nombre</span><span class="p">){</span>
<span class="nx">nombre</span> <span class="o">=</span> <span class="nx">_nombre</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">set_salario</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">_salario</span><span class="p">){</span>
<span class="nx">salario</span> <span class="o">=</span> <span class="nx">_salario</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//Código encapsulación</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">set_nombre</span> <span class="o">=</span> <span class="nx">set_nombre</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">set_salario</span> <span class="o">=</span> <span class="nx">set_salario</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">println</span> <span class="o">=</span> <span class="nx">println</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">that</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">empleado6</span> <span class="o">=</span> <span class="nx">newEmpleado6</span><span class="p">();</span>
<span class="nx">empleado6</span><span class="p">.</span><span class="nx">set_nombre</span><span class="p">(</span><span class="s2">"Pepe"</span><span class="p">);</span>
<span class="nx">empleado6</span><span class="p">.</span><span class="nx">set_salario</span><span class="p">(</span><span class="mi">750</span><span class="p">);</span>
<span class="nx">empleado6</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
</code></pre></div>
<ul>
<li>La ventaja de este enfoque es que los atributos son privados. Se pueden declarar métodos privados. Además, si un usuario del objeto modifica los métodos de este objeto, sólo afectará a los clientes del objeto, no a los métodos internos de la propia clase. Como parte negativa, este enfoque consume más memoria porque todo se declara en el objeto que se acaba de crear. El prototipo de este objeto es <code>Object.prototype</code>.</li>
<li>Hay que notar que la función <code>newEmpleado6</code> no es un constructor, por eso no está en mayúsculas y o se usa con <code>new</code>.</li>
<li>Cuando se usa el ámbito de una función para encapsula información se dice que se usa el patrón módulo (Module patter).</li>
</ul>
<h1>Herencia</h1>
<ul>
<li>La herencia se usa para crear una jerarquía de clasificación por especialización/generalización.</li>
<li>También para reutilizar código de la clase padre en las clases hijas.</li>
<li>Dependiendo se si hemos usado el enfoque basado en prototipos o el enfoque funcional, la herencia se implementa de una forma u otra.</li>
</ul>
<h3>Herencia con clases basadas en prototipos</h3>
<ul>
<li>Para hacer que una clase herede de otra en un sistema basado en prototipos, lo único que hay que hacer es que el prototipo sea un objeto de "clase padre".</li>
<li>Supongamos la clase Jefe5 (representada con el constructor Jefe5):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//Atributos</span>
<span class="kd">function</span> <span class="nx">Jefe5</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="s2">"Sin asignar"</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Herencia</span>
<span class="nx">Jefe5</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado5</span><span class="p">();</span>
<span class="c1">//Métodos</span>
<span class="nx">Jefe5</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">printDespacho</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Despacho: "</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">despacho</span><span class="p">);</span>
<span class="p">};</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">jefe5</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Jefe5</span><span class="p">();</span>
<span class="nx">jefe5</span><span class="p">.</span><span class="nx">nombre</span> <span class="o">=</span> <span class="s2">"Antonio"</span><span class="p">;</span>
<span class="nx">jefe5</span><span class="p">.</span><span class="nx">despacho</span> <span class="o">=</span> <span class="s2">"D333"</span><span class="p">;</span>
<span class="nx">jefe5</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
<span class="nx">jefe5</span><span class="p">.</span><span class="nx">printDespacho</span><span class="p">();</span>
</code></pre></div>
<p> Para cambiar el prototipo que tendrán los objetos creados con un constructor es necesario cambiar el prototipo asociado antes de crear un objeto con ese constructor. En el ejemplo es la línea:</p>
<div class="highlight"><pre><code class="javascript"> <span class="nx">Jefe5</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado5</span><span class="p">();</span>
</code></pre></div>
<p> Para más información sobre este tipo de herencia, conviene echar un vistazo a esta <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model">documentación de Mozilla</a>.</p>
<h2>Herencia con clases basadas en funciones</h2>
<ul>
<li>La herencia en este caso se hace usando el objeto de la clase padre para incializar el objeto that que se usará en la definición de la clase hija:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">newJefe6</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">//Atributos</span>
<span class="kd">var</span> <span class="nx">despacho</span> <span class="o">=</span> <span class="s2">"Sin asignar"</span><span class="p">;</span>
<span class="c1">//Métodos</span>
<span class="kd">var</span> <span class="nx">printDespacho</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Despacho: "</span><span class="o">+</span><span class="nx">despacho</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">set_despacho</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">_despacho</span><span class="p">){</span>
<span class="nx">despacho</span> <span class="o">=</span> <span class="nx">_despacho</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">//Herencia</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="nx">newEmpleado6</span><span class="p">();</span>
<span class="c1">//Código encapsulación</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">printDespacho</span> <span class="o">=</span> <span class="nx">printDespacho</span><span class="p">;</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">set_despacho</span> <span class="o">=</span> <span class="nx">set_despacho</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">that</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Uso del objeto</span>
<span class="kd">var</span> <span class="nx">jefe6</span> <span class="o">=</span> <span class="nx">newJefe6</span><span class="p">();</span>
<span class="nx">jefe6</span><span class="p">.</span><span class="nx">set_nombre</span><span class="p">(</span><span class="s2">"Antonio"</span><span class="p">);</span>
<span class="nx">jefe6</span><span class="p">.</span><span class="nx">set_despacho</span><span class="p">(</span><span class="s2">"D333"</span><span class="p">);</span>
<span class="nx">jefe6</span><span class="p">.</span><span class="nx">println</span><span class="p">();</span>
<span class="nx">jefe6</span><span class="p">.</span><span class="nx">printDespacho</span><span class="p">();</span>
</code></pre></div>
<h2>Acceso a atributos o métodos de la clase padre</h2>
<ul>
<li><p>Clases basadas en prototipos:</p>
<ul>
<li>Basta con acceder directamente al atributo en el objeto</li>
<li>El lenguaje se encarga de buscar el atributo o método en la cadena de prototipos (jerarquía de herencia).</li>
</ul>
</li>
<li><p>Clases basadas en funciones:</p>
<ul>
<li>Si la propiedad tiene método de acceso público, con el método de acceso.</li>
<li>Si no, hay que hacer una función de acceso utilizada por las clases hijas.</li>
<li>Esa función de acceso tiene que guardarse en un objeto interno que se utiliza para la comunicación entre los métodos de la jerarquía de herencia (objeto my).</li>
</ul>
</li>
</ul>
<h2>Redefinición de métodos</h2>
<ul>
<li>Basta con crear la nueva función y asignarla al objeto que se está creando para que se use esa en vez de la heredada.</li>
<li>Clases basadas en prototipos: El método redefinido será usado por cualquiera que usara ese método (clientes e implementación de la clase).</li>
<li>Clases basadas en funciones: El método redefinido será usado únicamente por los clientes y la implementación de las clases hijas).</li>
</ul>
<p>super para métodos:</p>
<h2>Reutilización de constructores</h2>
<ul>
<li>Clases basadas en prototipos: Creando el objeto prototipo.</li>
<li>Clases basadas en funciones: Creando el objeto that.</li>
</ul>
<h2>Reutilización de código basada en prototipos</h2>
<ul>
<li>En vez de crear jerarquías de herencia como clases hija y clases padre, se pueden crear relaciones entre objetos de forma más flexible.</li>
<li>Se puede crear un objeto simplemente indicando el objeto que actuará como prototipo, sin necesidad de usar un constructor.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">objetoProt</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">att1</span><span class="o">:</span> <span class="nx">value1</span><span class="p">;</span>
<span class="nx">att2</span><span class="o">:</span> <span class="nx">value2</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">objeto</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">objetoProt</span><span class="p">);</span>
<span class="nx">objeto</span><span class="p">.</span><span class="nx">att3</span> <span class="o">=</span> <span class="nx">value3</span><span class="p">;</span>
<span class="nx">objeto</span><span class="p">.</span><span class="nx">att4</span> <span class="o">=</span> <span class="nx">value4</span><span class="p">;</span>
</code></pre></div>
<h2>Polimorfismo</h2>
<ul>
<li>Se comporta como en Java.</li>
<li>En JavaScript cualquier variable puede tener como valor cualquier objeto de cualquier tipo (en Java únicamente si la variable se declara con la clase del objeto o una clase padre).</li>
<li>Como las variables no tienen tipo cuando se declaran, los métodos ejecutados en una variable serán siempre los métodos del objeto que exista en ese momento.</li>
</ul>
<h1>Funciones y objetos (la variable this)</h1>
<ul>
<li>La variable implícita this toma diferentes valores dependiendo de cómo se invoque la función que usa this.</li>
<li>Existen 4 formas de invocar una función en JavaScript:
<ul>
<li>Constructor Invocation Pattern</li>
<li>Method Invocation Pattern</li>
<li>Function Invocation Pattern</li>
<li>Apply Invocation Pattern</li>
</ul>
</li>
<li>A continuación se describe cada patrón y el significado de this.</li>
</ul>
<h2>Constructor Invocation Pattern</h2>
<ul>
<li>Se usa cuando una función se invoca como constructor (con el operador new)</li>
<li><code>this</code> apunta al objeto que se está creando.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="nx">lado</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">=</span> <span class="nx">lado</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">area</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">*</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="c1">//Constructor invocation pattern</span>
<span class="kd">var</span> <span class="nx">cuad</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
</code></pre></div>
<h2>Method Invocation Pattern</h2>
<ul>
<li>Cuando una función se invoca como un método de un objeto (con la notación punto)</li>
<li><code>this</code> apunta al objeto en el que se invoca el método.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="nx">lado</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">=</span> <span class="nx">lado</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">area</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">*</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="c1">//Constructor invocation pattern</span>
<span class="kd">var</span> <span class="nx">cuad</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="c1">//Method invocation pattern</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">cuad</span><span class="p">.</span><span class="nx">area</span><span class="p">());</span> <span class="c1">// Imprime 9</span>
</code></pre></div>
<h2>Function Invocation Pattern</h2>
<ul>
<li>Cuando una función se invoca de forma independiente a un objeto (usando su nombre).</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">suma</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">num1</span><span class="p">,</span> <span class="nx">num2</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">suma</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">6</span><span class="p">)</span> <span class="p">);</span> <span class="c1">//Imprime 9</span>
</code></pre></div>
<ul>
<li><code>this</code> apunta a un objeto global que existe en JavaScript.* Esto puede ser muy confuso en ciertos contextos. Por ejemplo, cuando se olvida poner el <code>new</code> al invocar un constructor, en realidad se invoca una función normal. La variable this se refiere al objeto global de JavaScript y se devuelve 'undefined'.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">cuad2</span> <span class="o">=</span> <span class="nx">Rectangulo</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">cuad2</span><span class="p">.</span><span class="nx">area</span><span class="p">());</span> <span class="c1">// TypeError porque cuad2 es undefined</span>
</code></pre></div>
<ul>
<li>Por ejemplo, si declaramos una función dentro de un método de un objeto y la función usa <code>this</code>, no accede al objeto en el que se declara (aunque en el ámbito en el que se encuentra this apunta a dicho objeto):</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//El siguiente código no funciona porque this apunta </span>
<span class="c1">//al objeto global en JavaScript en vez de al objeto </span>
<span class="c1">//en el que se ejecuta el método.</span>
<span class="kd">var</span> <span class="nx">pelicula</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Pelicula</span><span class="p">();</span>
<span class="nx">pelicula</span><span class="p">.</span><span class="nx">titulo</span> <span class="o">=</span> <span class="s2">"Borat"</span><span class="p">;</span>
<span class="nx">pelicula</span><span class="p">.</span><span class="nx">add_onclick_handler</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s2">"Película:"</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">pelicula</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Para solucionar este problema se define una variable llamada <code>that</code> y se asigna a <code>this</code>:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="c1">//El siguiente código si funciona porque that apunta </span>
<span class="c1">//al objeto en el que se ejecuta el método.</span>
<span class="kd">var</span> <span class="nx">pelicula</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Pelicula</span><span class="p">();</span>
<span class="nx">pelicula</span><span class="p">.</span><span class="nx">titulo</span> <span class="o">=</span> <span class="s2">"Borat"</span><span class="p">;</span>
<span class="nx">pelicula</span><span class="p">.</span><span class="nx">add_onclick_handler</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s2">"Película:"</span><span class="o">+</span><span class="nx">that</span><span class="p">.</span><span class="nx">pelicula</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">};</span>
</code></pre></div>
<h2>Apply Invocation Pattern</h2>
<ul>
<li>Este patron se utiliza cuando las funciones se utilizan como objetos.</li>
<li>Es una forma de reflexión porque permite tratar a las funciones de forma genérica de forma independiente a su nombre y número de parámetros.</li>
<li>Para invocar una función se invoca un método en la propia función con la notación punto. el método apply Se usan de la siguiente forma:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">suma</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">num1</span><span class="p">,</span> <span class="nx">num2</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//Function invocation pattern</span>
<span class="kd">var</span> <span class="nx">resultado</span> <span class="o">=</span> <span class="nx">suma</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">6</span><span class="p">)</span>
<span class="c1">//Apply invocation pattern</span>
<span class="kd">var</span> <span class="nx">resultado2</span> <span class="o">=</span> <span class="nx">suma</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="kc">null</span><span class="p">,[</span><span class="mi">3</span><span class="p">,</span><span class="mi">6</span><span class="p">]);</span>
</code></pre></div>
<ul>
<li>El primer parámetro de apply es el valor que tomará la variable implícita this al ejecutar la función.</li>
<li>El segundo valor de apply es un array con los parámetros que pasar a la función.</li>
<li>Cuando la función no usa <code>this</code>, se puede pasar <code>null</code>.</li>
<li>Cuando la función utiliza <code>this</code>, hay que pasar un objeto.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="nx">lado</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">=</span> <span class="nx">lado</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">area</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span> <span class="o">*</span> <span class="k">this</span><span class="p">.</span><span class="nx">lado</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="c1">//Constructor invocation pattern</span>
<span class="kd">var</span> <span class="nx">cuad</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Cuadrado</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="c1">//Method invocation pattern</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">cuad</span><span class="p">.</span><span class="nx">area</span><span class="p">()</span> <span class="p">);</span> <span class="c1">// Imprime 9</span>
<span class="kd">var</span> <span class="nx">areaObj</span> <span class="o">=</span> <span class="nx">cuad</span><span class="p">.</span><span class="nx">area</span><span class="p">;</span>
<span class="c1">//Apply invocation pattern</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">areaObj</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">cuad</span><span class="p">)</span> <span class="p">);</span>
</code></pre></div>
<h1>Excepciones</h1>
<ul>
<li>Las excepciones son conceptualmente igual que en Java.</li>
<li>Existe un bloque <code>try {} catch(e) {} finally {}</code> como en Java.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">try</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="p">...;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="s2">"An error"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span> <span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
<span class="c1">//do cleanup, etc here</span>
<span class="p">}</span>
</code></pre></div>
<ul>
<li>El operador throw puede lanzar como excepción un valor de tipo string, number, boolean o un objeto.</li>
<li>Lo recomendable es devolver un objeto con atributos name y message.</li>
</ul>
<h1>Reflexión</h1>
<ul>
<li>La reflexión es una técnica de programación que permite tratar a los objetos como si fueran valores.</li>
<li>En ciertos contextos se conoce como "meta-programación"</li>
<li>Con la reflexión se puede inspeccionar a los elementos del lenguaje para conocer más información sobre ellos antes de realizar una tarea.</li>
<li>La reflexión se considera una técnica avanzada de programación y en general existen formas más sencillas y directas de implementar un programa.</li>
</ul>
<h2>Reflexión en valores</h2>
<h3>Operador typeof</h3>
<ul>
<li>Operador prefijo que devuelve el tipo de un valor</li>
<li>Conceptualmente similar a .class de los objetos en Java</li>
<li>Devuelve el tipo como uno de los strings: 'number', 'string', 'object', 'function', 'undefined', 'boolean'. En un navegador también puede devolver 'xml'.</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof">Más información sobre typeof</a>.</li>
<li>Por ejemplo, para ejecutar un código si un valor es de tipo 'string':</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">variable</span> <span class="o">===</span> <span class="s1">'string'</span><span class="p">){</span>
<span class="c1">//...</span>
<span class="p">}</span>
</code></pre></div>
<h2>Reflexión en objetos</h2>
<h3>Conocer el tipo de un objeto</h3>
<ul>
<li>Es un operador infijo que compara un valor con un constructor para saber si esa función se utilizó para crear el objeto o uno de sus prototipos.</li>
<li>Conceptualmente similar al instanceof de Java</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">function</span> <span class="nx">Empleado</span><span class="p">()</span> <span class="p">{}</span>
<span class="kd">function</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="p">{}</span>
<span class="nx">Jefe</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Empleado</span><span class="p">();</span>
<span class="k">new</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Jefe</span><span class="p">;</span> <span class="c1">// true</span>
<span class="k">new</span> <span class="nx">Jefe</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Empleado</span><span class="p">;</span> <span class="c1">// true</span>
</code></pre></div>
<h3>Acceso a las propiedades de un objeto</h3>
<ul>
<li>Se puede recorrer la lista de propiedades de un objeto (atributos y métodos) para poder tratar objetos de forma genérica:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">objeto</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">propiedad</span><span class="o">+</span><span class="s2">": "</span><span class="o">+</span><span class="nx">objeto</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div>
<ul>
<li>Usando typeof se puede acceder sólo a los atributos, no a los métodos.</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">objeto</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">valorPropiedad</span> <span class="o">=</span> <span class="nx">objeto</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">valorPropiedad</span> <span class="o">!==</span> <span class="s1">'function'</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">propiedad</span><span class="o">+</span><span class="s2">": "</span><span class="o">+</span><span class="nx">valorPropiedad</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
</code></pre></div>
<ul>
<li>Se puede determinar si una propiedad está en el objeto o en su cadena de prototipos:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">propiedad</span> <span class="k">in</span> <span class="nx">objeto</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">objeto</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">propiedad</span><span class="p">))</span>
<span class="kd">var</span> <span class="nx">valorPropiedad</span> <span class="o">=</span> <span class="nx">objeto</span><span class="p">[</span><span class="nx">propiedad</span><span class="p">];</span>
<span class="c1">//...</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h3>Obtener el prototipo de un objeto</h3>
<ul>
<li>Todos los objetos tienen un prototipo.</li>
<li>Se puede acceder a él con el método:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">objeto</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">prototipo_obj</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getPrototypeOf</span><span class="p">(</span><span class="nx">objeto</span><span class="p">);</span>
</code></pre></div>
<h2>Reflexión en funciones</h2>
<ul>
<li>Independientemente de los parámetros que tenga declarados, una función puede acceder a los parámetros con los que se ha invocado de forma genérica.</li>
<li>Toda función tiene un parámetro implícito llamado <code>arguments</code> que contiene los valores con los que se ha invocado:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span> <span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">sum</span> <span class="o">+=</span> <span class="nx">arguments</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<ul>
<li>Como <code>arguments</code> no es realmente un array, no tiene métodos. Para usar métodos de un array en <code>arguments</code> se puede usar este patrón:</li>
</ul>
<div class="highlight"><pre><code class="javascript"> <span class="kd">var</span> <span class="nx">slice</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">arrayArgs</span> <span class="o">=</span> <span class="nx">slice</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);</span>
</code></pre></div>
<h1>Métodos de tipos básicos y arrays</h1>
<ul>
<li>Existe una librería estándar en forma de métodos de los valores de tipos básicos. Se verá en otra entrada del blog.</li>
</ul>
<div id="note">
<p>Este post forma parte de una de una serie de posts en los que cuento mi viaje por las tecnologías de front-end, esas que permiten implementar aplicaciones web interactivas. Todo ello desde el punto de vista de un programador Java con más de 10 años de experiencia. Si te interesa puedes echar un vistazo a las demás entradas:</p>
<ul>
<li>Parte 1: <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Viaje por las tecnologias de front end</a></li>
<li>Parte 2: <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Primer contacto con JavaScript</a>,</li>
<li>Parte 3: <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">Orientacion a Objetos en JavaScript comparado con Java</a></li>
<li>Parte 4: <a href="/blog/JavaScript-no-es-orientado-a-objetos">JavaScript no es orientado a objetos</a></li>
</ul>
</div>
Viaje por las tecnologías de "front-end" (Parte 1)2013-12-22T00:00:00-08:00http://micaelgallego.github.com/blog/Viaje-por-las-tecnologias-de-front-end<p>Yo soy un desarrollador de software un poco atípico. Por mi trabajo como profesor, sólo puedo dedicar parte de mi
tiempo de trabajo a programar. La otra parte la dedico a preparar material docente, corregir, leer libros de diversas tecnologías, etc.
Además, en el último año también me he dedicado principalmente a la gestión de equipos y dirección técnica. Si me conoces,
sabes que me saqué el <a href="http://micaelgallego.blogspot.com.es/2013/05/soy-scrummaster-certificado-e-intento.html">certificado de Scrum Master</a> hace un año.</p>
<p>En el campo de la informática en general y del desarrollo software en particular, siempre hay que mantenerse al día. Yo siempre
intento mantenerme al día de mis tecnologías preferidas. Suelo estar bastante informado de las tecnologías relacionadas con Java
(Spring, Maven, Gradle, Java 8, Programación Concurrente en Java, Java EE, Android, ...). También me intereso por las buenas prácticas
(TDD, XP, Clean code, Agile, ...). Y debido al área de investigación al que me dedico, también suelo estar al día de diseño de algoritmos
de optimización.</p>
<p>Nunca he estado muy al día de las tecnologías web porque nunca he trabajado en ese área. Hace casi 10 años (en el 2004) impartí
varios cursos de desarrollo web con Java: Servlets, JSP, HTML, JDBC. Hasta llegué a publicar un <a href="http://www.foibg.com/ijita/vol13/ijita13-1-p10.pdf" title="Hi!MVC: Hierarchical MVC Framework for Web Applications">artículo sobre el tema</a>.
Por aquel entonces eso era la web. Pero obviamente las cosas han
cambiado muchísimo desde aquellos días. Hace un par de años impartí la asignatura de Desarrollo de Aplicaciones Web en la <a href="http://www.urjc.es">URJC</a> y
me reciclé bastante. Me puse al día con Java EE (EJB, JSF, JPA,...), pero la parte de front-end (HTML, CSS, JS, AJAX, ...) la impartió
otro profesor, así que no me puse mucho con esa parte.</p>
<p>Durante el año pasado estuve en contacto con la tecnología web. Aunque yo no programé la parte cliente, estaba de <em>scrum master</em>
y arquitecto de una aplicación web y móvil. La aplicación se llama <a href="http://www.welvi.es">welvi</a> y ofrece entrenamiento personal y servicios de actividad física.
El caso es que estuvimos evaluando muchas tecnologías y muchas arquitecturas diferentes para implementar welvi. Decidimos implementar una API REST
consumida por las aplicaciones de cliente (Web JavaScript, Android, iOS y Samsung Smart TV). La tecnología de back-end la teníamos bastante
clara. Se implementó con Spring y Tomcat. Estuvimos evaluando Mongo como sistema de persistencia y finalmente nos convenció.</p>
<p>Pero el caso de front-end fue más complicado. Al principio estuvimos evaluando si hacer una web tradicional (en la que el servidor
genera HTML) o bien una web con cliente JavaScript (<a href="http://en.wikipedia.org/wiki/Single-page_application">Single Page Application</a>). Finalmente decidimos el enfoque de <em>Single Page Application</em>.
Esa arquitectura nos permitía que la web fuera mucho más fluida e interactiva y además nos permitía implementar un único back-end con una API REST
para todos los clientes.</p>
<p>Y ahí empezó la explosión de tecnologías, técnicas, librerías, herramientas y frameworks para implementar la parte cliente, el front-end. Mi amigo
<a href="http://www.linkedin.com/pub/anthanh-pham-trinh/38/502/b05">Anthanh Pham</a> se encargó de bucear en este mar de caos y confusión para implementar el front-end de welvi. Después de varios meses de
búsqueda, análisis, pruebas y prototipos, nos quedamos con las siguientes tecnologías, librerías, frameworks y herramientas:</p>
<ul>
<li><strong>HTML</strong>: Se usó únicamente contenido semántico para estructurar contenido.</li>
<li><strong>CSS</strong>: Se utilizó <a href="http://sass-lang.com/">SASS</a> como herramienta de generación de CSS con <a href="http://compass-style.org/">COMPASS</a>.</li>
<li><strong>JavaScript</strong>
<ul>
<li><strong>Lenguaje</strong>
<ul>
<li>Sólo usamos <a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742">las partes buenas</a>. No nos hizo falta <a href="http://coffeescript.org/">CoffeScript</a>.</li>
<li>Intentamos no meter la pata usando <a href="hhttp://jslint.com/">jslint</a> y <a href="http://www.jshint.com/docs/">jshint</a>.</li>
<li>Tenemos en cuenta los <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/">patrones de diseño</a> y el <a href="http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html">patrón módulo</a>.</li>
<li>El código se "comprime" con <a href="https://github.com/mishoo/UglifyJS">UglifyJS</a>.</li>
<li>Las dependencias en "runtime" se gestionan con <a href="http://requirejs.org/">Requiere.js</a></li>
</ul>
</li>
<li><strong>Librerías / Frameworks</strong>
<ul>
<li><a href="http://jquery.com/">jQuery</a> para mejorar y unificar el acceso al DOM y otras funcionalidades del navegador.</li>
<li><a href="http://underscorejs.org/">Underscore</a> para gestionar las estructuras de datos y otras funciones de utilidades.</li>
<li><a href="http://backbonejs.org/">Backbone</a> Framework MVC con modelos y eventos ante cambios en el modelo.</li>
<li><a href="http://marionettejs.com/">Marionette</a> Librería de gestión de vista de Backbone.</li>
</ul>
</li>
<li><strong>Gráficos</strong>
<ul>
<li><a href="http://getbootstrap.com/">Bootstrap</a> Como librería de componentes gráficos.</li>
</ul>
</li>
<li><strong>Compatibilidad de navegadores</strong>
<ul>
<li>Usamos <a href="http://modernizr.com/">Modernizr</a> para gestionar la compatibilidad con los navegadores con (<a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills">Pollyfills</a>)</li>
</ul>
</li>
</ul>
</li>
<li><strong>Herramientas</strong>
<ul>
<li><a href="http://yeoman.io/">Yeoman</a> para generar el esqueleto de la aplicación con las dependencias necesarias</li>
<li><a href="http://gruntjs.com/">Grunt</a> para ejecutar las tareas en el ciclo de vida del software (construcción, empaquetado, ejecución de test, etc...)</li>
<li><a href="http://bower.io/">Bower</a> para gestionar las dependencias en "tiempo de construcción" (basado en <a href="http://nodejs.org/">Node.js</a> y <a href="https://npmjs.org/">NPM</a>)</li>
</ul>
</li>
</ul>
<p>También usamos tecnologías de testing, pero eso lo dejamos para otra entrada.</p>
<p>Mi objetivo es ponerme al día con todas estas tecnologías. Por mi propio interés (nunca hay que quedarse atrás) y para poder
contar algo de esto en la asignatura que estoy a punto de empezar a la vuelta de Navidades. La web ha cambiado mucho desde la última vez que
estuve trabajando con ella, así que toca actualizarse.</p>
<p>Iré contanto mis peripecias en este viaje en más entradas sobre el <strong>Viaje por las tecnologías de "front-end"</strong></p>
<div id="note">
<p>Este post forma parte de una de una serie de posts en los que cuento mi viaje por las tecnologías de front-end, esas que permiten implementar aplicaciones web interactivas. Todo ello desde el punto de vista de un programador Java con más de 10 años de experiencia. Si te interesa puedes echar un vistazo a las demás entradas:</p>
<ul>
<li>Parte 1: <a href="/blog/Viaje-por-las-tecnologias-de-front-end">Viaje por las tecnologias de front end</a></li>
<li>Parte 2: <a href="/blog/Viaje-por-las-tecnologias-de-front-end2">Primer contacto con JavaScript</a>,</li>
<li>Parte 3: <a href="/blog/Orientacion-a-Objetos-en-JavaScript-comparado-con-Java">Orientacion a Objetos en JavaScript comparado con Java</a></li>
<li>Parte 4: <a href="/blog/JavaScript-no-es-orientado-a-objetos">JavaScript no es orientado a objetos</a></li>
</ul>
</div>
Jugando con imágenes2013-12-22T00:00:00-08:00http://micaelgallego.github.com/blog/Jugando-con-imagenes<p>En este post voy a hacer algunas pruebas con imágenes en un post. Para insertar una imagen
parece que basta con tener el fichero en una carpeta del sitio y hacer una referencia a
dicha imagen.</p>
<p>No he visto ningún mecanismo para que Jekyll gestione las imágenes de una forma algo más
inteligente, como por ejemplo, el reescalado automático.</p>
<p>Mi primera imagen en un blog va a ser el logo de Jekyll.</p>
<p><img src="/img/posts/2013-12-22/jekyll.png" alt="Jekyll" /></p>
<p>Para que se vea la imagen, he puesto el siguiente código en el post:</p>
<pre><code>![Jekyll](/img/posts/2013-12-22/jekyll.png)
</code></pre>
<p>Como se puede intuir, la parta más laboriosa de trabajar con imágenes está en que hay que darles
nombre y crear una carpeta por cada entrada para que no se mezclen.</p>
<p>Buscando por la red he visto <a href="https://github.com/robwierzbowski/jekyll-picture-tag">un plugin</a> de Jekyll que hace el reescalado de las imágenes para
varias resoluciones. El problema es que si usamos plugins de Jekyll, no podremos aprovecharnos de
la generación automática del sitio por GitHub y tendremos que generar nosotros las páginas en
local antes de subirlas. Si tenemos instalado Jekyll en local para previsualizar, esto no debería
ser un problema, pero el flujo no es tan automático.</p>
Mi nuevo blog2013-12-21T00:00:00-08:00http://micaelgallego.github.com/blog/Mi-nuevo-blog<p>Hoy estreno nuevo blog. Aunque por fuera parezca un blog normal, por dentro es muy diferente a los
blogs "tradicionales".</p>
<p>Como puedes ver por la URL http://micaelgallego.github.io, el blog está alojado
en GitHub, la forja y red social para desarrolladores. La diferencia fundamental con otros tipos de
blogs es que este blog es una página estática que se genera automáticamente partiendo de código wiki.
En concreto, el formato de wiki es Markdown y la herramienta de generación es <a href="http://jekyllrb.com/">Jekyll</a>.</p>
<p>El objetivo es tener una forma más sencilla y más directa de escribir entradas del blog que incluyan
código fuente. Quizás cambie de opinión, pero creo que para mi es más sencillo escribir un nuevo post
en un fichero de texto en mi ordenador que conectado a una págin web de wordpress o blogger. Además,
la sintaxis wiki es más amigable para escribir sobre código que escribir directamente en un editor wysiwyg
online.</p>
<p>Al principio no entendía bien el workflow para crear el blog en github, pero después de echar un vistazo
a varias páginas ya me he enterado:</p>
<ul>
<li>Existe un generador de sitios web basado en formato wiki Markdown llamado <a href="http://jekyllrb.com/">Jekyll</a>.</li>
<li>Este generado se puede usar en local y tiene un sistema de generación automática cuando el fichero cambia.</li>
<li>Este sistema también está integrado en github, de forma que el contenido en formato wiki se transforma
automáticamente en HTML antes de ser publicado. Esto puede ser un poco confuso al principio, pero tiene
la ventaja de que una vez creado el sitio, sólo tienes que preocuparte de subir ficheros en formato wiki
a git y la página se genera de forma automática.</li>
</ul>
<p>Si tenéis ganas de probar, os recomiendo echar un vistazo a <a href="http://yeswejekyll.com/">este blog</a>.
La versión básica de Jekyll es un poco "minimalista", pero he encontrado
<a href="http://erjjones.github.io/blog/How-I-built-my-blog-in-one-day/">este blog</a> y me ha ayudado a poner a
punto este sitio. Graficamente no es muy impactante, pero creo que cumple el objetivo, es fácil de editar.</p>
<p>Lo que ocurre es que ahora tengo que aprender un poco de Markdown. Yo soy más de Textile (el formato
de wiki que usa Redmine). He encontrado esta página con información sobre <a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a> que me está sirviendo como guía rápida.</p>