<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>EtnasSoft</title> <atom:link href="http://www.etnassoft.com/feed/" rel="self" type="application/rss+xml" /><link>http://www.etnassoft.com</link> <description>Programación Web y arquitectura Javascript en Madrid</description> <lastBuildDate>Wed, 22 Feb 2012 11:32:03 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Creando objetos y aplicaciones configurables en Javascript</title><link>http://www.etnassoft.com/2012/01/24/creando-objetos-y-aplicaciones-configurables-en-javascript/</link> <comments>http://www.etnassoft.com/2012/01/24/creando-objetos-y-aplicaciones-configurables-en-javascript/#comments</comments> <pubDate>Tue, 24 Jan 2012 11:32:10 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[configuración]]></category> <category><![CDATA[extend]]></category> <category><![CDATA[objetos]]></category> <category><![CDATA[POO]]></category> <category><![CDATA[prototipo]]></category> <category><![CDATA[Prototype]]></category> <category><![CDATA[valores por defecto]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=2292</guid> <description><![CDATA[Introducción Aquellos que estén más familiarizados con la programación de plugins para jQuery, conocen de sobra el método $.extend() de esta biblioteca. Gracias a él, podemos definir una serie de valores por defecto para nuestras aplicaciones (objetos) que se sobreescriben &#8230; <a
class="more-link" href="http://www.etnassoft.com/2012/01/24/creando-objetos-y-aplicaciones-configurables-en-javascript/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Aquellos que estén más familiarizados con la programación de plugins para jQuery, conocen de sobra el método $.extend() de esta biblioteca. Gracias a él, <strong>podemos definir una serie de valores por defecto para nuestras aplicaciones</strong> (objetos) que se sobreescriben solo en caso de que éstos se especifiquen a su inicialización.</p><p>Este tipo de comportamiento, que identificable con el concepto de herencia clásica en la POO, podemos obtenerlo también en nuestras aplicaciones sin necesidad de recurrir a bibliotecas de terceros.</p><p>Veamos una forma sencilla de crear un objeto con una serie de valores por defecto que pueden ser sobreescritos desde su propia API.<span
id="more-2292"></span></p><h2>El método Extend</h2><p>Lo primero que tenemos que hacer es <strong>crear una función que nos permita &#8216;extender&#8217; fácilmente un objeto preexistente</strong>.</p><p>Para este ejercicio, vamos a considerar el extender la primitiva nativa Object de Javascript.</p><p><em>NOTA: Sobre el hecho de extender primitivas, se ha escrito mucho. Si no nos gusta esta vía, siempre podemos crear una función simple que nos haga el trabajo. Para ver las ventajas o problemas de cada uno de estos métodos, se recomienda la lectura del artículo &#8220;<a
href="http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/">Extending Javascript Natives</a>&#8221; del bueno de Angus Croll.</em></p><p>El código, muy simple, sería:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">Object.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">extend</span> <span style="color: #339933;">=</span> Object.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">extend</span> <span style="color: #339933;">||</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>destination<span style="color: #339933;">,</span> source<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> property <span style="color: #000066; font-weight: bold;">in</span> source<span style="color: #009900;">&#41;</span>
    destination<span style="color: #009900;">&#91;</span>property<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> source<span style="color: #009900;">&#91;</span>property<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> destination<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>Con esto, hemos extendido a <em>Object</em> con un nuevo método <em>extend</em>. Este método aceptaría dos argumentos: el objeto destino (<em>destination</em>) que presumiblemente ya cuenta con una serie de valores establecidos y el objeto origen (<em>source</em>) que debe sobreescribir el anterior allí donde haya coincidencias.</p><p>El método anterior podríamos complicarlo mucho más con comprobaciones de todo tipo, pero para la intención de este artículo, con la funcionalidad indicada es suficiente: <strong>se trata de un bucle que recorre las propiedades del objeto <em>source</em> y las va escribiendo en el objeto <em>destination</em>. Finalmente, devuelve este último objeto ya modidificado</strong>.</p><h2>Implementando el nuevo método</h2><p>Tomemos ahora el siguiente escenario: estamos desarrollando una aplicación, biblioteca o plugin y<strong> necesitamos asignarle una serie de valores por defecto</strong>. Estos valores permiten mucha flexibilidad a la hora de configurar nuestra funcionalidad.</p><p>Por ejemplo:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> my App <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Default settings</span>
  <span style="color: #003366; font-weight: bold;">var</span> settings <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    fullScreen <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    backgroundColor <span style="color: #339933;">:</span> <span style="color: #3366CC;">'#000'</span><span style="color: #339933;">,</span>
    speed <span style="color: #339933;">:</span> <span style="color: #CC0000;">20</span>
    <span style="color: #009966; font-style: italic;">/* and so on... */</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>Se trataría en este caso de ir añadiendo propiedades que más adelante <strong>necesitaremos que estén iniciadas con algún tipo de valor por defecto</strong>. En el código anterior, hemos incluido como ejemplo una opción para una supuesta pantalla completa, un color de fondo y algún parámetro de velocidad. Podría ser este el código inicial de un carrusel o un <em>slideshow</em> tradicional.</p><p>Tendríamos ahora que permitir mediante un API de esta biblioteca, que el usuario o desarrollador pudiera sobreescribir estos valores para configurar la herramienta a su gusto. Algo que permitiera, por ejemplo:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">myApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  fullScreen <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
  backgroundColor <span style="color: #339933;">:</span> <span style="color: #3366CC;">'#FFF'</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>La idea sería modificar en tiempo de ejecución los valores por defecto anteriores para que tanto la propiedad <em>fullScreen</em> como <em>backgroundColor</em> tomasen los nuevos valores. Por omisión, <em>speed</em> conservaría su valor inicial.</p><p>Para implementar esta funcionalidad a través de nuestro nuevo método <em>extend</em>, solo tendríamos que hacer una pequeña modificación en el código de nuestra biblioteca-aplicación:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>customSettings<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// Default settings</span>
  <span style="color: #003366; font-weight: bold;">var</span> settings <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    fullScreen <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    backgroundColor <span style="color: #339933;">:</span> <span style="color: #3366CC;">'#000'</span><span style="color: #339933;">,</span>
    speed <span style="color: #339933;">:</span> <span style="color: #CC0000;">20</span>
    <span style="color: #009966; font-style: italic;">/* and so on... */</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  customSettings <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span> customSettings <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  Object.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span> settings<span style="color: #339933;">,</span> customSettings <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009966; font-style: italic;">/* Awesome more methods goes here */</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> settings<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Only for testing</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>Y ya lo tendríamos!</p><p>Nuestro objeto se inicia con una serie de valores por defecto, pero ahora, <strong>acepta además un argumento que se corresponde con las opciones introducidas por el desarrollador</strong> o usuario.</p><p>Estas <em>customSettings</em> extienden a las <em>default settings</em> modificando sus valores en tiempo de ejecución. El <em>return</em> no sería necesario en una aplicación real, pero para este ejercicio permite ver cómo hemos efectivamente modificado los valores iniciales.</p><p>Podemos comprobarlo si ahora ejecutamos el ejemplo anterior:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> test <span style="color: #339933;">=</span> myApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  fullScreen <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
  backgroundColor <span style="color: #339933;">:</span> <span style="color: #3366CC;">'#FFF'</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>test<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>El resultado que obtenemos son nuestras opciones de configuración modificadas salvo en aquellos casos en los que, por omisión, se mantienen las establecidas por defecto. Cualquier método a partir de ahí en nuestra aplicación podría disponer de estos valores para realizar las operaciones y funcionalidades oportunas.</p><h2>Conclusión</h2><p>Con esta sencilla fórmula, podemos crear aplicaciones muy flexibles que permitan un alto grado de configuración. Se trata del mismo principio aplicado a muchas bibliotecas de terceros como pueden ser, por ejemplo, los plugins de jQuery.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=2292&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2012/01/24/creando-objetos-y-aplicaciones-configurables-en-javascript/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>El valor de this en Javascript: cómo manejarlo correctamente</title><link>http://www.etnassoft.com/2012/01/12/el-valor-de-this-en-javascript-como-manejarlo-correctamente/</link> <comments>http://www.etnassoft.com/2012/01/12/el-valor-de-this-en-javascript-como-manejarlo-correctamente/#comments</comments> <pubDate>Thu, 12 Jan 2012 11:42:03 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[apply]]></category> <category><![CDATA[call]]></category> <category><![CDATA[dispatch]]></category> <category><![CDATA[oop]]></category> <category><![CDATA[POO]]></category> <category><![CDATA[this]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=2247</guid> <description><![CDATA[Introducción this es un valor complejo en Javascript; un error en el diseño del lenguaje susceptible de causar tanto comportamientos inesperados como potentes estructuras de código reutilizable. Su valor, lejos de ser intuitivo, se determina según la forma en que &#8230; <a
class="more-link" href="http://www.etnassoft.com/2012/01/12/el-valor-de-this-en-javascript-como-manejarlo-correctamente/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p><em>this</em> es un valor complejo en Javascript; un error en el diseño del lenguaje susceptible de causar tanto comportamientos inesperados como potentes estructuras de código reutilizable. Su valor, lejos de ser intuitivo, se determina según la forma en que se invoque a la función que lo encierra, algo que no siempre es correctamente entendido o aprovechado.</p><p>Dado que el correcto manejo de <em>this</em> resulta esencial en la programación orientada a objetos, y en definitiva en el desarrollo moderno de aplicaciones, es interesante dedicar unos minutos a revisarlo.</p><h2>Qué es exactamente this</h2><p>La palabra clave <em>this</em> tiene en Javascript un comportamiento diferente al de otros lenguajes pero por lo general, <strong>su valor hace referencia al propietario de la función que la está invocando o en su defecto, al objeto donde dicha función es un método</strong>.</p><p>La palabra clave del párrafo anterior es &#8220;<strong>propietario</strong>&#8220;.<br
/> <span
id="more-2247"></span><br
/> Cuando no estamos dentro de una estructura definida, esto es un objeto con métodos, el propietario de una función es siempre el contexto global. En el caso de los navegadores web, tenemos que recordar que dicho objeto es <em>window</em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">this</span> <span style="color: #339933;">===</span> window <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #006600; font-style: italic;">// true</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">this</span> <span style="color: #339933;">===</span> window<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
test<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span></pre></div></div><h2>Accediendo a los valores de un objeto desde el propio objeto</h2><p>Este concepto de propietario puede inducir a errores. Pensemos en un objeto con una serie de propiedades:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">name</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Megan'</span><span style="color: #339933;">,</span>
  lastName <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Fox'</span><span style="color: #339933;">,</span>
  birthDate <span style="color: #339933;">:</span> <span style="color: #3366CC;">'16/05/1986'</span><span style="color: #339933;">,</span>
  isPretty <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myApp.<span style="color: #000066;">name</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Megan</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myApp.<span style="color: #660066;">isPretty</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span></pre></div></div><p>Supongamos ahora que necesitamos otra propiedad más &#8216;dinámica&#8217; que participe de los valores asignados a cualquier otra. Por ejemplo, queremos un &#8216;<em>completeName</em>&#8216; que concatene &#8216;<em>name</em>&#8216; y &#8216;<em>lastName</em>&#8216;. Parece que este un claro ejemplo de uso para <em>this</em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">name</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Megan'</span><span style="color: #339933;">,</span>
  lastName <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Fox'</span><span style="color: #339933;">,</span>
  completeName <span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastName</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Aunque parece coherente, cuando pasamos a comprobarlo vemos que el resultado no es el esperado:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myApp.<span style="color: #660066;">completeName</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// undefined</span></pre></div></div><p>El problema aquí es que <em>this</em> no está apuntando al objeto como cabría esperar, sino que está buscando la referencia fuera, en el contexto global (<em>window</em>).</p><p>Para obtener el resultado esperado tenemos que aplicar un patrón de invocación que modifique al propietario desde el que se invoca el <em>this</em>&#8230;</p><h2>Patrón de invocación por método</h2><p>En Javascript, existen varias formas de llamar a las funciones desde nuestro código; concretamente, <a
href="http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx">podemos enumerar hasta cinco diferentes</a>. La elección de una u otra responde al flujo de nuestro programa pero básicamente, difieren en el contexto que queramos aplicar a cada una. O lo que es lo mismo, al valor que queramos que la función asigne a la referencia <em>this</em>.</p><p>En el desarrollo de aplicaciones modernas, el patrón más recurrente es el de invocación por método: <strong>una función es almacenada como propiedad de un objeto convirtiéndose así en lo que denominamos un método</strong>.</p><p>Cuando llamamos (invocamos) a un método, <em>this</em> hace refencia al propio objeto:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">name</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Megan'</span><span style="color: #339933;">,</span>
  lastName <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Fox'</span><span style="color: #339933;">,</span>
  completeName <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">' '</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastName</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myApp.<span style="color: #660066;">completeName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Megan Fox</span></pre></div></div><p>En esta ocasión, si podemos comprobar como <em>this</em> apunta al propio objeto y busca la propiedades &#8216;<em>name</em>&#8216; y &#8216;<em>lastName</em>&#8216; <em>dentro</em> en lugar de remontarse hasta el contexto global.</p><p>Pero como vimos en el caso anterior, no siempre el uso de <em>this</em> es intuitivo. Consideremos la siguiente estructura:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;World&quot;</span>
  <span style="color: #003366; font-weight: bold;">var</span> sayHello <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello, '</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  sayHello<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Invoke the function</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
myApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello,</span></pre></div></div><p>¿A dónde está apuntando <em>this</em> en este caso? Como la función no es ahora la propiedad de un objeto, <em>this</em> apunta de nuevo al global (<em>window</em>). Esto es un <a
href="http://javascript.crockford.com/javascript.html">error en el diseño del lenguaje</a> ya que, de comportarse como se espera, <em>this</em> debería apuntar a la función contenedora (que no deja de ser su propietaria).</p><p>Este comportamiento lo podemos comprobar si creamos una variable global con aquel nombre por el que estamos preguntando:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Strange World&quot;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;World&quot;</span>
  <span style="color: #003366; font-weight: bold;">var</span> sayHello <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello, '</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  sayHello<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
myApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello, Strange World</span></pre></div></div><p>La consecuencia de este error es que <strong>un método no puede utilizar funciones internas que la ayuden a hacer su trabajo porque éstas, no tiene acceso a sus propiedades</strong>.</p><p>Para resolver este problema, podemos recurrir a una solución muy simple: <strong>definir dentro de nuestra función contenedora una nueva variable que cachee el valor de <em>this</em></strong> para que así esté disponible desde cualquier otra función anidada que lo precise. <strong>Por convención, el nombre de esta variable es <em>that</em></strong>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myApp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> that <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Work around!</span>
  <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">name</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;World&quot;</span>
  <span style="color: #003366; font-weight: bold;">var</span> sayHello <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello, '</span> <span style="color: #339933;">+</span> that.<span style="color: #000066;">name</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  sayHello<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
myApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello, World</span></pre></div></div><p><em>NOTA: Últimamente, la convención que propuso Douglas Crockford está siendo revisada y son muchos los desarrolladores que prefieren el término self para referirse al objeto cacheado.</em></p><h2>Sobreescribiendo el valor de this en tiempo de ejecución</h2><p>Una de las características consideradas avanzadas dentro del lenguaje Javascript es la posibilidad de reescribir el valor de <em>this</em> en tiempo de ejecución consiguiendo así una modularidad y reusabilidad extrema.</p><p>Más arriba comentamos que existen varias formas de invocar funciones en Javascript donde la elección entre una u otra depende del valor que queramos asignar a <em>this</em>.</p><p>Consideremos el siguiente codigo:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> person1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">name</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Angelina'</span><span style="color: #339933;">,</span>
  lastName <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Jolie'</span><span style="color: #339933;">,</span>
  birthDay <span style="color: #339933;">:</span> <span style="color: #3366CC;">'04/06/1975'</span><span style="color: #339933;">,</span>
  lastMovie <span style="color: #339933;">:</span> <span style="color: #3366CC;">'The Tourist'</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> person2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066;">name</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Scarlett'</span><span style="color: #339933;">,</span>
  lastName <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Johansson'</span><span style="color: #339933;">,</span>
  birthDay <span style="color: #339933;">:</span> <span style="color: #3366CC;">'22/11/1984'</span><span style="color: #339933;">,</span>
  lastMovie <span style="color: #339933;">:</span> <span style="color: #3366CC;">'We bought a Zoo'</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> printName <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">' '</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastName</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Si tratamos de ejecutar sin más la función <em>printName</em>, ya sabemos que el <em>this</em> apunta al objeto global <em>window</em> e irá ahí a buscar las propiedas <em>name</em> y <em>lastName</em>.</p><p>En una arquitectura modular, lo ideal es que esa función pueda ser reaprovechada y que nos permita imprimir los datos de cualquier objeto que cumpla con los requisitos. Para ello, podemos cambiar el valor de <em>this</em> en tiempo de ejecución con el fin de que apunte <strong>a ese objeto en cuestión</strong>. Para ello, contamos con las funciones nativas <em><a
href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply">apply</a></em> y <em><a
href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call">call</a></em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">printName.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span> person1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Angelina Jolie</span>
printName.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span> person2 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Scarlett Johansson</span>
&nbsp;
printName.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span> person1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Angelina Jolie</span>
printName.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span> person2 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Scarlett Johansson</span></pre></div></div><p>El resultado es el mismo: hemos ejecutado la función <em>printName</em> dentro del contexto de cada uno de los objetos que hemos pasado como argumento.</p><p>La diferencia entre cada uno de estas funciones es que la segunda de ellas, <em>apply</em>, <strong>acepta un array como argumento</strong>, lo que permite una flexibilidad aún mayor a la hora de plantear código reusable.</p><p>Pensemos en una función que nos permita actualizar datos dentro de nuestros objetos:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> updatePerson <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">,</span> lastName<span style="color: #339933;">,</span> birthDay<span style="color: #339933;">,</span> lastMovie<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">=</span> <span style="color: #000066;">name</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastName</span> <span style="color: #339933;">=</span> lastName<span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">birthDay</span> <span style="color: #339933;">=</span> birthDay<span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastMovie</span> <span style="color: #339933;">=</span> lastMovie<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
updatePerson<span style="color: #009900;">&#40;</span> person1<span style="color: #339933;">,</span> <span style="color: #3366CC;">'Angelina'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Jolie'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'04/06/1975'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Kung Fu Panda 2'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Las limitaciones de <em>call</em> se hacen rápidamente evidentes cuando queremos escribir código que no conoce (o no debe conocer) el número de argumentos que la función necesita.</p><p>Tomemos por ejemplo una función que siga el conocido paradigma del &#8216;<em><a
href="http://en.wikipedia.org/wiki/Dynamic_dispatch">dispatcher</a></em>&#8216;:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dispatch <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>person<span style="color: #339933;">,</span> method<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  method.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span> person<span style="color: #339933;">,</span> args <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
dispatch<span style="color: #009900;">&#40;</span> person1<span style="color: #339933;">,</span> printName <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dispatch<span style="color: #009900;">&#40;</span> person2<span style="color: #339933;">,</span> update<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'Scarlett'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Johansson'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'22/11/1982'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'The Avengers'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>En este caso, el poder jugar con el valor de <em>this</em> y además asociar una serie de datos a través de un array, permite una poderosa flexibilidad a la hora de escribir código reutilizable.</p><h2>Conclusión</h2><p>El valor de <em>this</em> ha sido siempre difícil de manejar en Javascript. Las pequeñas diferencias que presenta frente a otros lenguajes así como un error en su diseño, lo hacen francamente especial. Sin embargo, esa peculiaridad, es precisamente la que permite crear un tipo de código muy versátil una vez que conocemos sus secretos.</p><p>Manejarlo correctamente es una parte esencial dentro del desarrollo de aplicaciones complejas en Javascript.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=2247&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2012/01/12/el-valor-de-this-en-javascript-como-manejarlo-correctamente/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Midiendo el rendimiento de nuestros objetos canvas (Contador FPS)</title><link>http://www.etnassoft.com/2011/12/16/midiendo-el-rendimiento-de-nuestros-objetos-canvas-contador-fps/</link> <comments>http://www.etnassoft.com/2011/12/16/midiendo-el-rendimiento-de-nuestros-objetos-canvas-contador-fps/#comments</comments> <pubDate>Fri, 16 Dec 2011 10:28:46 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[canvas]]></category> <category><![CDATA[fps]]></category> <category><![CDATA[html5]]></category> <category><![CDATA[rendimiento]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=2162</guid> <description><![CDATA[Introducción Preparando una aplicación basada íntegramente en canvas me topé con el blog del Proyecto Cyan, un interesante proyecto en español sobre la elaboración videojuegos en Javascript a través de un framework propio que han bautizado como piNgine. Entre sus &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/12/16/midiendo-el-rendimiento-de-nuestros-objetos-canvas-contador-fps/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Preparando una aplicación basada íntegramente en <em>canvas</em> me topé con el blog del <a
href="http://www.project-cyan.com">Proyecto Cyan</a>, un interesante proyecto en español sobre la elaboración videojuegos en Javascript a través de un framework propio que han bautizado como <strong>piNgine</strong>.</p><p>Entre sus diversos y recomendables artículos, uno de los primeros trata sobre <a
href="http://www.project-cyan.com/2011-06-calcular-y-mostrar-fps-html5-canvas/">la medición del rendimiento de un objeto canvas según el número de FPS</a> (<a
href="http://es.wikipedia.org/wiki/Im%C3%A1genes_por_segundo">imágenes por segundo</a>) que es capaz de gestionar. Como es bien sabido en la industria del videojuego, éste es un valor esencial a la hora de buscar cuellos de botella y zonas pesadas que son susceptibles de mejorar.<span
id="more-2162"></span></p><h2>Cómo va eso de los FPS</h2><p>Cuando estamos trabajando con entornos gráficos, como puede ser el caso del canvas, las operaciones de redibujado son constantes: la sensación de animaciones o desplazamientos se resuelven mediante un ciclo de limpiado y renderizado de las zonas afectadas.</p><p><strong>Este proceso conlleva un coste y es mesurable</strong>. Los FPS vienen a indicar la cantidad de veces que una zona, generalmente el <em>viewport</em> (la pantalla completa) se redibuja por segundo.</p><p>Suele considerarse que una tasa óptima <strong>está alrededor de los 40 fps</strong>. Valores por debajo de los 20-15 indican sobrecarga y deberían ser objeto de atención para un posible optimizado (reduciendo el número de objetos visibles, modificando el algoritmo de compresión, etc&#8230;).</p><h2>Midiendo los FPS en un canvas</h2><p>Para realizar esta medición, solo necesitamos aplicar una rutina que realice un conteo de los refrescos del objeto canvas sobre el que estamos trabajando.</p><p>Para facilitar la reutilización, lo ideal <strong>es crear un objeto que podamos cargar con un JS externo</strong> y que nos permita iniciarlo a voluntad para controlar los valores que arroje.</p><p>Me he permitido tomar el código de piNgine al que he realizado algunas modificaciones.</p><p>Su API es sumamente sencilla. Para comenzar el conteo, únicamente debemos iniciar el objeto:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">fpsCounter.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span> canvasID <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Donde:<br
/> - <em>canvasID</em> (opcional) es el ID del objeto que deseamos monitorizar. Si omitimos este valor, el objeto busca un canvas con ID <em>canvas</em> (el más frecuente).</p><p><em>NOTA: He decidido que el objeto no busque los objetos canvas automáticamente en el DOM porque existen técnicas muy extendidas como los <a
href="http://kaioa.com/node/103">buffers que crean falsos canvas</a> de sustitución para actuar como zonas de prerenderizado. Aplicar el conteo de FPS sobre esas zonas no tendría sentido por lo que es el desarrollador el que debe proporcionar el ID del objeto que desea estudiar.</em></p><p>El código es el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fpsCounter <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Modulo de FPS cargado...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// FPS máximos a los que queremos que se ejecute la aplicación.</span>
  <span style="color: #003366; font-weight: bold;">var</span> maxfps <span style="color: #339933;">=</span> <span style="color: #CC0000;">32</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Variables necesarias para el recuento de FPS y el cálculo del delay.</span>
  <span style="color: #003366; font-weight: bold;">var</span> frameCount <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
      currentFps <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span>
      drawInterval <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span> <span style="color: #339933;">/</span> maxfps <span style="color: #339933;">*</span> <span style="color: #CC0000;">1000</span><span style="color: #339933;">,</span>
      lastFps <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Variables para almacenar las referencias al elemento canvas.</span>
  <span style="color: #003366; font-weight: bold;">var</span> canvas <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span>
      ctx <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Método que utilizamos como constructor.</span>
  <span style="color: #003366; font-weight: bold;">var</span> initCore <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> canvasID <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Inciando el contador de FPS...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Cargamos el objeto canvas y su contexto</span>
    canvas <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> canvasID <span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> canvasID <span style="color: #339933;">:</span> <span style="color: #3366CC;">'canvas'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> canvas <span style="color: #339933;">&amp;&amp;</span> canvas.<span style="color: #660066;">getContext</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      ctx <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'2d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #006600; font-style: italic;">// Inicializamos el intervalo a los FPS deseados.</span>
      setInterval<span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> startApp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> drawInterval <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
      console.<span style="color: #660066;">warn</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Objeto canvas no encontrado o navegador no soportado!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> startApp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Actualizamos y enviamos la petición de pintado.</span>
    update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    draw<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> update <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Calculamos el tiempo desde el último frame.</span>
    <span style="color: #003366; font-weight: bold;">var</span> thisFrame <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        diffTime <span style="color: #339933;">=</span> Math.<span style="color: #660066;">ceil</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>thisFrame <span style="color: #339933;">-</span> lastFps<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>diffTime <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">1000</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      currentFps <span style="color: #339933;">=</span> frameCount<span style="color: #339933;">;</span>
      frameCount <span style="color: #339933;">=</span> <span style="color: #CC0000;">0.0</span><span style="color: #339933;">;</span>
      lastFps <span style="color: #339933;">=</span> thisFrame<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    frameCount<span style="color: #339933;">++;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> draw <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Pintamos los datos en el canvas</span>
    ctx.<span style="color: #660066;">clearRect</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">width</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ctx.<span style="color: #660066;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ctx.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'#000'</span><span style="color: #339933;">;</span>
    ctx.<span style="color: #660066;">font</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bold 10px sans-serif'</span><span style="color: #339933;">;</span>
    ctx.<span style="color: #660066;">fillText</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'FPS: '</span> <span style="color: #339933;">+</span> currentFps <span style="color: #339933;">+</span> <span style="color: #3366CC;">'/'</span> <span style="color: #339933;">+</span> maxfps<span style="color: #339933;">,</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">15</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ctx.<span style="color: #660066;">restore</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span><span style="color: #009900;">&#123;</span>
    init <span style="color: #339933;">:</span> initCore
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p><em>NOTA: Durante el código, se realizan algunas llamadas a la consola (console.log); si nuestro navegador no dispone de esa funcionalidad, solo tenemos que comentar aquellas líneas en las que aparezca esa referencia.</em></p><p>Para aplicar este <em>script</em>, podemos crear una sencilla página de prueba:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">&lt;!doctype html&gt;
&lt;html lang=&quot;es&quot;&gt;
&lt;head&gt;
  &lt;title&gt;Contador FPS&lt;/title&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;/js/fpsCounter.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;canvas id=&quot;canvas&quot; width=&quot;200px&quot; height=&quot;200px&quot; style=&quot;border:1px solid #000;&quot;&gt;
  &lt;p&gt;¡Explorador no compatible!&lt;/p&gt;
&lt;/canvas&gt;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
fpsCounter.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span>
&lt;/body&gt;
&lt;/html&gt;</pre></div></div><p><strong>Podemos ver el resultado <a
href="http://www.etnassoft.com/test/fps-counter.html">aquí</a></strong>.</p><p>Si leemos el código, hemos establecido una tasa máxima de FPS por segundo:</p><pre>var maxfps = 32;</pre><p>Este valor es muy útil para garantizar que nuestra aplicación <strong>corre a la misma velocidad máxima con independencia de la potencia de la plataforma sobre la que la ejecutemos</strong>. Un valor de 32 suele ser suficiente pero, como hemos comentado anteriormente, podemos escoger otros más altos si necesitamos una mayor fluidez.</p><p>Por defecto, los FPS se muestran en la parte superior del canvas; si queremos cambiar esta localización, solo tendremos que tocar la función <em>draw()</em>.</p><h2>Conclusión</h2><p>Sin duda, esta rutina puede resultar muy útil mientras trabajamos con <em>canvas</em> o estamos pensando en portar un proyecto al interesante sistema WebGL. Controlar la tasa de refresco es importante para identificar problemas de rendimiento y ponernos en sobre aviso.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=2162&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/12/16/midiendo-el-rendimiento-de-nuestros-objetos-canvas-contador-fps/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>El nuevo objeto jQuery $.Callbacks()</title><link>http://www.etnassoft.com/2011/11/22/el-nuevo-objeto-jquery-callbacks/</link> <comments>http://www.etnassoft.com/2011/11/22/el-nuevo-objeto-jquery-callbacks/#comments</comments> <pubDate>Tue, 22 Nov 2011 08:08:15 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[callbacks]]></category> <category><![CDATA[deferred]]></category> <category><![CDATA[funciones. stacks]]></category> <category><![CDATA[listas]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=2068</guid> <description><![CDATA[Introducción En el post anterior revisamos los nuevos métodos on() y off() de la versión 1.7 de jQuery, sin duda, una de las innovaciones más interesantes. Siguiendo con el estudio de esta versión, nos toca ahora echarle un vistazo a &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/11/22/el-nuevo-objeto-jquery-callbacks/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>En el post anterior revisamos <a
title="Los nuevos métodos jQuery on() y off()" href="http://www.etnassoft.com/2011/11/21/los-nuevos-metodos-jquery-on-y-off/">los nuevos métodos <em>on()</em> y <em>off()</em></a> de la versión <a
href="http://jquery.com/">1.7 de jQuery</a>, sin duda, una de las innovaciones más interesantes.</p><p>Siguiendo con el estudio de esta versión, nos toca ahora echarle un vistazo a otra importante novedad: el objeto <em><a
href="http://api.jquery.com/jQuery.Callbacks/">$.Callbacks()</a></em>.</p><p>Básicamente, <strong><em>$.Callbacks</em> ofrece un completo <em>stack</em> (conjunto de elementos) donde definir una serie de funciones que serán ejecutadas en secuencia como resultado de una determinada condición o acción previa</strong>.</p><p>Como la explicación puede resultar confusa, comencemos con un ejemplo para ir luego avanzando con cada uno de los métodos que ofrece este nuevo elemento:<br
/> <span
id="more-2068"></span></p><h2>Ejemplo de $.Callbacks</h2><p>Tenemos dos funciones como las siguientes:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fn1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> myStr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Fn1 says: '</span><span style="color: #339933;">,</span> myStr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> fn2 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> myStr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Fn2 says '</span><span style="color: #339933;">,</span> myStr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Bien; nada complejo: dos funciones simples que reciben un argumento para pintarlo en la consola. Ahora, asociemos ambas funciones al nuevo objeto <em>$.Callbacks</em> para crear una pila o cola de ejecución con ellas:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello World'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Fn1 says: Hello World</span>
&nbsp;
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn2 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Goodbye Lenin'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Fn1 says: Goodbye Lenin, Fn2 says: Goodbye Lenin</span></pre></div></div><p>Como podemos comprobar, hemos utilizado dos métodos que prácticamente hablan por si mismos: <strong><em>add()</em></strong> y <strong><em>fire()</em></strong>. El primero, se encarga de añadir una función al <em>stack</em> o pila mientras que el segundo, <em>fire()</em>, se encarga de ejecutar dicha pila a la vez que permite que enviemos argumentos a la misma.</p><p>Junto a estos dos métodos, contamos con un tercero también básico: <strong><em>remove()</em></strong>, el cual permite, como su nombre indica, borrar una referencia determinada de nuestra lista. Su uso es igual de simple:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> double <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #339933;">*</span> <span style="color: #CC0000;">2</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myVal<span style="color: #339933;">,</span> <span style="color: #3366CC;">' is not Numeric!'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #003366; font-weight: bold;">var</span> triple <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myVal <span style="color: #339933;">*</span> <span style="color: #CC0000;">3</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myVal<span style="color: #339933;">,</span> <span style="color: #3366CC;">' is not Numeric!'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> double <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">5</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 10</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'foo'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// foo is not Numeric!</span>
&nbsp;
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> triple <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">10</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 20, 30</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'bar'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// bar is not Numeric!</span>
&nbsp;
stack.<span style="color: #660066;">remove</span><span style="color: #009900;">&#40;</span> double <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">2</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 6</span></pre></div></div><p>Lo primero es comentar el uso de otra de las nuevas funcionalidades de jQuery 1.7: <a
href="http://api.jquery.com/jQuery.isNumeric/">la función <em>isNumeric()</em></a>. Con ella comprobamos <strong>si un determinado valor se corresponde con un valor numérico, independientemente de que se le pase como entero o cadena</strong>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'10'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'one'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $.<span style="color: #660066;">isNumeric</span><span style="color: #009900;">&#40;</span>NaN<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span></pre></div></div><p><em>NOTA: la última comprobación puede resultar confusa ya que para Javascript, <a
title="Coerción de datos en Javascript" href="http://www.etnassoft.com/2011/04/06/coercion-de-datos-en-javascript/">NaN se corresponde con un valor númerico</a>. jQuery, sin embargo, considera que NaN no se corresponde con un número.</em></p><p>Volviendo al ejemplo anterior, vemos como <em>remove()</em> suprime una determinada función del <em>stack</em>. Pero si en lugar de una concreta, quisiéramos eliminar todas las funciones que hayamos incluído en nuestra pila, contamos con el método <strong><em>empty()</em></strong> para vaciarla de forma inmediata:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">stack.<span style="color: #660066;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> stack.<span style="color: #660066;">has</span><span style="color: #009900;">&#40;</span> triple <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span></pre></div></div><p><em>NOTA: El método has() lo revisaremos más adelante en este mismo artículo.</em></p><h2>Separando pilas</h2><p>Dado que, como hemos visto en los ejemplos anteriores, las pilas se asocian a variables, podemos tener varios entornos de forma simultánea.</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> calcDouble <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> calcTriple <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
calcDouble.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> double <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
calcTriple.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> triple <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
calcDouble.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">10</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 20</span>
calcTriple.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">20</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 60</span></pre></div></div><p>Con esto, podemos tener varias colas o listas de ejecución independientes.</p><h2>Otros métodos</h2><p>Además de <em>add</em>, <em>fire</em> y <em>remove</em>, <em>$.Callbacks</em> soporta otros métodos que pueden resultar muy interesantes:</p><p><strong>fireWith()</strong>: con este método, se puede especificar el contexto y los argumentos que se pasamos a la pila:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> sum <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> result <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> x<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> i<span style="color: #339933;">=</span>arguments.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;</span> i<span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    result <span style="color: #339933;">+=</span> arguments<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> result <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> sum <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
stack.<span style="color: #660066;">fireWith</span><span style="color: #009900;">&#40;</span> window<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 20</span></pre></div></div><p>En el ejemplo anterior, hemos creado una función <em>sum</em> que devuelve la suma de todos aquellos valores que se le pasan como argumentos. Para ejecutarla desde nuestra pila, hemos utilizado el <em>fireWith</em> pasándole como contexto <em>window</em> y como argumentos un array con diversos valores.</p><p>Tenemos que tener en cuenta aquí que lo que recibe la función <em>sum</em> no es el array, sino que cada uno de los valores que hemos indicado se correspondería con un argumento en nuestra función:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> sum <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/* arg1, arg2, arg3, ... */</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">//...</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p><strong>has():</strong> este método sirve para determinar si una función concreta forma parte de nuestra pila.</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fn1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello World'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> fn2 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Goodbye Lenin'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> stack.<span style="color: #660066;">has</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> stack.<span style="color: #660066;">has</span><span style="color: #009900;">&#40;</span> fn2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span></pre></div></div><p><strong>fired():</strong> este método determina si una determinada lista ha sido ejecutada al menos una vez:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> foo <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> value <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'foo:'</span> <span style="color: #339933;">+</span> value <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> foo <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'hello'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// foo: hello</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'world '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// foo: world</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> stack.<span style="color: #660066;">fired</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// true</span></pre></div></div><p><strong>disable():</strong> este método inutiliza la lista e impide la ejecución de la misma en futuras llamadas:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> foo <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> value <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> value <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> foo <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'foo'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// foo</span>
&nbsp;
stack.<span style="color: #660066;">disable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'foobar'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// foobar isn't output so nothing is printed</span></pre></div></div><p><strong>lock() y locked()</strong>: el primer método bloquea la lista para impedir que pueda ser modificada de forma dinámica desde el interior de la misma. El segundo método comprueba si la lista ha sido bloqueada devolviendo un valor booleano.</p><h2>Indicadores</h2><p>El objeto <em>$.Callbacks()</em> <strong>soporta además indicadores o <em>flags</em></strong> que determinan el comportamiento de la lista. Estos indicadores se especifican al iniciar el objeto y se corresponden con una serie de palabras reservadas separadas por comas. Los posibles valores son:</p><ul><li><strong>once</strong>: especifica que la lista solo se ejecutará una vez (igual que <em><a
title="El nuevo objeto Deferred en jQuery 1.5" href="http://www.etnassoft.com/2011/02/02/el-nuevo-objeto-deferred-en-jquery-1-5/">Deferred</a></em>).</li><li><strong>memory</strong>: al igual que en Deferred, los valores previos se memorizan por lo que a cada llamada de la lista, éstos se tienen en cuenta.</li><li><strong>unique</strong>: asegura que las funciones que forman una lista, solo se pueden incluir una vez evitando duplicados.</li><li><strong>stopOnFalse</strong>: interrumpe la pila de ejecución cuando alguna de las funciones devuelve un valor <em>false</em>.</li></ul><p>Algunos ejemplos:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fn1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Fn1 says: '</span> <span style="color: #339933;">+</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> fn2 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> str <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Fn2 says: '</span> <span style="color: #339933;">+</span> str <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> callbacks <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;memory&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
callbacks.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
callbacks.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;foo&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
callbacks.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn2 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
callbacks.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;bar&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Fn1 says: foo</span>
<span style="color: #006600; font-style: italic;">// Fn2 says: foo</span>
<span style="color: #006600; font-style: italic;">// Fn1 says: bar</span>
<span style="color: #006600; font-style: italic;">// Fn2 says: bar</span></pre></div></div><p>En el caso anterior, aunque <em>fn2</em> no estaba incluida en la lista antes de la primera ejecución (<em>fire</em>), al si estarlo más adelante en el código, funciona devolviendo el valor &#8216;memorizado&#8217; en <em>fn1</em>.</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fn1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello World'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'unique'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello World</span>
&nbsp;
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// repeat addition</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello World --&gt; only once</span></pre></div></div><p>Aunque hemos incluido un par de veces la función <em>fn1</em>, gracias al indicador <em>unique</em> ésta solo se ejecuta una vez.</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fn1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Hello World'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> fn2 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Goodbye Lenin'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'stopOnFalse'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span> fn1<span style="color: #339933;">,</span> fn2 <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
stack.<span style="color: #660066;">fire</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hello World</span></pre></div></div><p>En esta ocasión, aunque dentro de nuestra lista estarían definidas las funciones <em>fn1</em> y <em>fn2</em>, al devolver la primera un <em>false</em> y habiendo especificado el indicador <em>stopOnFalse</em>, la ejecución se interrumpe inmediatamente.</p><p>Para definir más de un indicador al mismo tiempo, solo tenemos que separarlos con espacios:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> $.<span style="color: #660066;">Callbacks</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'unique stopOnFalse'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><h2>Conclusión</h2><p>Pues esto es todo; un nuevo objeto jQuery con el que contar en nuestro inventario para programar <em>callbacks</em> de forma precisa.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=2068&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/11/22/el-nuevo-objeto-jquery-callbacks/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Los nuevos métodos jQuery on() y off()</title><link>http://www.etnassoft.com/2011/11/21/los-nuevos-metodos-jquery-on-y-off/</link> <comments>http://www.etnassoft.com/2011/11/21/los-nuevos-metodos-jquery-on-y-off/#comments</comments> <pubDate>Mon, 21 Nov 2011 07:55:50 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript / AJAX]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[bind]]></category> <category><![CDATA[delegate]]></category> <category><![CDATA[eventos]]></category> <category><![CDATA[Javascript]]></category> <category><![CDATA[live]]></category> <category><![CDATA[off]]></category> <category><![CDATA[on]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=2056</guid> <description><![CDATA[Introducción Con la llegada de jQuery 1.7, se han solucionado varios bugs que esta biblioteca arrastraba de versiones anteriores; también se ha mejorado una vez más el rendimiento general de la misma prestándose especial atención a selectores y a la &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/11/21/los-nuevos-metodos-jquery-on-y-off/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Con la llegada de <a
href="http://jquery.com/">jQuery 1.7</a>, se han solucionado varios bugs que esta biblioteca arrastraba de versiones anteriores; también se ha mejorado una vez más el rendimiento general de la misma prestándose especial atención a selectores y a la portabilidad a los dispositivos móviles.</p><p>Pero además de estos &#8216;arreglos&#8217;, tenemos nuevos métodos y nuevas funcionalidades interesantes. De entre los primeros, sin duda los más interesantes son los que se refieren a la nueva gestión de eventos: el corazón de jQuery.</p><h2>Los eventos en jQuery</h2><p>Desde su aparición, jQuery se ha caracterizado por la flexibilidad con la que el desarrollador puede efectuar selecciones de elementos dentro del DOM y por la facilidad para asociar eventos a cada uno de esos conjuntos seleccionados.</p><p>Sin embargo, un problema con el que han tenido que lidiar los chicos del jQuery Team es que, con el paso de las versiones, estos manejadores (<em>handlers</em>) se han multiplicado hasta resultar confusos en las últimas <em>releases</em>.<span
id="more-2056"></span></p><p>Al principio, solo disponíamos del viejo método <em>bind</em> con el que asignábamos un determinado evento a un objeto jQuery:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mySelector'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// The callback goes here...</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></div></div><p>Para aquellos eventos muy frecuentes, como en el caso del <em>click</em> anterior, contábamos incluso con prácticos atajos (<em>shortcuts</em>):</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mySelector'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// The callback goes here...</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>El problema de <em>bind</em> es que solo funciona con aquellos elementos del DOM que ya están presentes cuando la función se ejecuta. Es decir, aquellos otros elementos que pudieran añadirse de forma dinámica, no heredan este comportamiento.</p><p>Para solventar este problema, apareció en escena el método <em>live()</em>. Sin embargo, <em>live</em> presentaba más problemas que ventajas y rápidamente se consideró obsoleto (<em>deprecated</em>). El problema con este método proviene de su bajo rendimiento en estructuras complejas y de algunos comportamientos impredecibles que se dan en determinados escenarios. Para un completo artículo sobre el porqué no debemos usar jQuery live, podemos leer <a
title="Porqué no debemos usar nunca jQuery Live" href="http://www.etnassoft.com/2011/05/12/porque-no-debemos-usar-nunca-jquery-live/">un artículo escrito hace algún tiempo en este blog sobre ese respecto</a>.</p><p>Buscando una vía alternativa al uso de <em>live</em>, jQuery ofreció un nuevo método muy similar: <em>delegate()</em>. Hasta el momento, <em>delegate</em> ha tratado de cubrir la funcionalidad de asociar eventos a elementos DOM pero, de nuevo, el resultado no ha sido todo lo satisfactorio que cabría esperar.</p><p>Es por todo esto que, frente a la confusión por parte del desarrollador de encontrarse tantos métodos similares (bind, live, delegate, one, &#8230;), el jQuery Team ha decidido crear dos nuevos métodos que aúnen el comportamiento de todos ellos buscando el máximo rendimiento y minimizando la confusión: <em>on()</em> y <em>off()</em>.</p><h2>El método on()</h2><p>El objetivo de <em>on()</em> es reemplazar a los antiguos <em>bind</em>, <em>live</em> y <em>delegate</em>. Su sintaxis es la siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>elements<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span>events <span style="color: #009900;">&#91;</span><span style="color: #339933;">,</span> selector<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#91;</span><span style="color: #339933;">,</span> data<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> handler<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Donde:</p><ul><li><strong>events</strong> son los eventos que se buscan asociar al conjunto de elementos seleccionados. La novedad aquí es que pueden asociarse más de un evento separándolos con espacios. Por ejemplo: &#8216;click&#8217;, &#8216;click blur&#8217;.</li><li><strong>selector</strong> especifica los descendientes de los elementos seleccionados que dispararán el evento. Se trata de un parámetro opcional.</li><li><strong>data</strong> indica cualquier tipo de datos que se necesite pasar al manejador cuando se dispara el evento. Es también un parámetro opcional y, por lo general, se corresponde con un objeto jQuery.</li><li><strong>handler</strong> se corresponde con el callback o acción a realizar después de que el evento se dispare.</li></ul><p>Un ejemplo de uso completo puede ser el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#myContainer .item'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  click<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'item clicked'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  mouseenter<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enter!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>El resultado del código anterior es que hemos asociado dos eventos diferentes, con dos callbacks diferentes a aquellos elementos DOM que cumplan con el criterio de la selección (en este caso aquellos con la clase &#8216;item&#8217; descendientes de un ID &#8216;myContainer&#8217;). Como hemos comentando más arriba, al reemplazar a <em>live()</em> y <em>delegate()</em>, este comportamiento será heredado por cualquier otro elemento que se inserte en el DOM de forma dinámica aún después de haber sido ejecutada la función anterior.</p><h2>Actualizaciones desde métodos antiguos</h2><p>Actualizar nuestros viejos códigos a la nueva versión resulta por lo general sencillo:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Old live() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#myContainer .item'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">live</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'item clicked'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// New on() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#myContainer'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.item'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'item clicked'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>En el ejemplo anterior hemos visto además, como se asocian selectores dentro del propio cuerpo de la función para especificar aquellos descendientes que dispararán el evento.</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Old delegate() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#myContainer'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">delegate</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.item'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'item clicked'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// New on() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#myContainer'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'.item'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'item clicked'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>En el caso de la actualización desde <em>delegate</em>, solo necesitamos cambiar el orden de los parámetros.</p><h2>El método off()</h2><p>Al igual que con la asocación de eventos, la confusión de métodos también llegaba con la acción contraria: eliminarlos.</p><p>Para esta acción, contábamos con varios métodos como <em>unbind()</em>, <em>die()</em> o <em>undelegate()</em>. De nuevo, el objetivo principal de la nueva instrucción es reemplazarlos a todos de un modo consistente.</p><p>La sintaxis de <em>off()</em> resulta similar a la de <em>on()</em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>elements<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">off</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span> events <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#91;</span><span style="color: #339933;">,</span> selector<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#91;</span><span style="color: #339933;">,</span> handler<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Con <em>off()</em>, todos los parámetros son opcionales. Cuando se utiliza en su forma más simple, $(elements).off(), se eliminan todos los eventos asociados al conjunto seleccionado.</p><h2>Actualizaciones desde métodos antiguos</h2><p>Como en el caso anterior, dependiendo de qué método vengamos, la conversión presenta más o menos cambios.</p><p>Para el caso de <em>unbind()</em>, solo necesitamos cambiar el nombre del método:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Old unbid() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// New off() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">off</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Para aquellos códigos que hagan uso del <em>live() / die()</em>, el cambio es similar:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Old die() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">die</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// New off() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">off</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>De nuevo, solo es necesario organizar ligeramente el orden de los parámetros para aprovechar la nueva potencia del método <em>off()</em>.</p><p>Para la portabilidad desde <em>undelegate()</em>, solo tenemos que cambiar el orden de los parámetros:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Old undelegate() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">undelegate</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'click'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// New off() style:</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#container a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">off</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><h2>Conclusión</h2><p>Con la nueva versión 1.7 de jQuery, se trata por fin de poner algo de orden en cuanto al manejo de eventos que ofrece esta biblioteca, aunando en unos mismos métodos toda la funcionalidad que hasta la fecha se había ido desplegando en varios.</p><p>Con esto, el resultado es un API más robusto y sólido, exactamente lo que los desarrolladores jQuery han solicitado al equipo de desarrollo.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=2056&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/11/21/los-nuevos-metodos-jquery-on-y-off/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>Signos de que eres un mal desarrollador</title><link>http://www.etnassoft.com/2011/10/26/signos-de-que-eres-un-mal-desarrollador/</link> <comments>http://www.etnassoft.com/2011/10/26/signos-de-que-eres-un-mal-desarrollador/#comments</comments> <pubDate>Wed, 26 Oct 2011 12:10:36 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Programación]]></category> <category><![CDATA[algoritmia]]></category> <category><![CDATA[array]]></category> <category><![CDATA[funciones]]></category> <category><![CDATA[objetos]]></category> <category><![CDATA[oop]]></category> <category><![CDATA[patrón]]></category> <category><![CDATA[POO]]></category> <category><![CDATA[programación]]></category> <category><![CDATA[refactorizar]]></category> <category><![CDATA[tipado]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=1961</guid> <description><![CDATA[Introducción Siguiendo en la línea de los artículos que @ialcazar considera como &#8216;esos que despiertan conciencias&#8216;, he querido traer ahora un escrito original de Lawrence Wenham donde desarrolló un listado de signos (con sus síntomas y remedios) que identificarían a &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/10/26/signos-de-que-eres-un-mal-desarrollador/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Siguiendo en la línea de los artículos que <a
href="twitter.com/ialcazar">@ialcazar</a> considera como &#8216;<em>esos que despiertan conciencias</em>&#8216;, he querido traer ahora un escrito original de <a
href="http://stackoverflow.com/users/5548/c-lawrence-wenham">Lawrence Wenham</a> donde desarrolló un listado de signos (con sus síntomas y remedios) que identificarían a los malos desarrolladores.</p><p>El objetivo de este artículo no es otro sino el de motivarnos a continuar aprendiendo ya que es perfectamente aplicable a cada uno de nosotros en el momento de enfrentarnos a una nueva tecnología. Me gusta aquí recordar como <a
href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin">Rober Martin</a> siempre aconseja que, para mejorar como desarrolladores, tenemos que salirnos frecuentemente de nuestra zona de confort, buscando nuevos retos en lenguajes que supongan un paradigma radicalmente opuesto al que manejamos en nuestro día a día.</p><p>Si decidimos dar el salto del <a
href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_imperativa">paradigma imperativo</a> al <a
href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_declarativa">declarativo</a>, podemos necesitar de algún tipo de rasero que nos indique si ya estaríamos preparados para aplicar los nuevos conocimientos a un entorno real de producción.</p><p>Veámos cuáles podrían ser los síntomas de si hemos o no comprendido lo que tenemos entre manos&#8230;</p><p><span
id="more-1961"></span></p><h2>1. Incapacidad para razonar sobre un código dado</h2><p>Incapacidad para razonar un código significa que <strong>no podemos seguir mentalmente el hilo de ejecución aún sabiendo su finalidad</strong>. Es decir, deberíamos contar con la habilidad de ejecutar un programa en nuestra cabeza sin necesidad de recurrir al compilador o intérprete.</p><h4><strong>Síntomas</strong></h4><ul><li>Presencia de códigoue no tiene ningún efecto sobre el objetivo final de un programa pero que se continúa manteniendo. Por ejemplo, hablamos de variables que se inician pero nunca se utilizan, llamadas a funciones que resultan irrelevantes para el objetivo final, valores de salida que no se utilizan, etc&#8230;</li><li>Reiteradas llamadas a un mismo bloque de código (por ejemplo, llamar a una función <em>save()</em> varias veces únicamente para <em>estar seguros</em>).</li><li>Reparar errores escribiendo código que sobreescribe ese resultado erróneo. Por ejemplo, en lenguajes de tipado blando, si detectamos que una variable que debería contener un entero contiene una cadena, reescribimos su valor asignándole cero.</li><li><em>Código yo-yo</em> que convierte un valor <em>algo diferente</em> para un cubrir un paso concreto de ejecución y luego retoma el valor original. Por ejemplo, convertir un valor decimal en una cadena, operar sobre él, y luego devolverlo a su forma decimal inicial.</li><li><em>Código bulldozer</em> que da la impresión de refactorizar alguna estructura pero que, en realidad, resulta imposible de reutilizar fuera de su propio contexto.</li></ul><h4><strong>Remedios</strong></h4><p>Para superar estas deficiencias, un programador debe practicar usando un buen IDE junto a su debugger favorito; esto le permitirá avanzar por un código paso a paso de modo que pueda seguir fácilmente su hilo de ejecución. Esto significa por ejemplo <strong>crear puntos de ruptura y monitorizar el valor de determinadas variables</strong> antes y después de cada cambio hasta entender qué es lo que está haciendo el código.</p><p>El objetivo es alcanzar ese punto donde podríamos fácilmente leer un código, identificar duplicados o estructuras innecesarias. Además de esto, mejoraremos la habilidad de detectar y corregir errores sin tener que reescribir todo desde cero por el simple hecho de que no sabemos leer lo existente.</p><h2>2. Comprensión pobre del modelo de programación de un determinado lenguaje</h2><p>La <a
href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos">Programación Orientada a Objetos</a> (POO u OOP) es un ejemplo de modelo de lenguaje, como lo es la programación funcional o declarativa. Éstos poseen a su vez diferencias significativas con otros <a
href="http://es.wikipedia.org/wiki/Paradigma_de_programaci%C3%B3n">paradigmas</a> como el imperativo, del mismo modo en el que, por ejemplo, la <a
href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_estructurada">programación estructural</a> es muy diferente del <a
href="http://es.wikipedia.org/wiki/Lenguaje_ensamblador">ensamblador</a> o de una programación basada en <a
href="http://es.wikipedia.org/wiki/GOTO">GOTO</a>.</p><p><strong>Existen lenguajes que se adscriben a un determinado modelo (como por ejemplo la POO) pero que presentan sus propias mejoras (<em>features</em>) sobre los mismos.</strong></p><h4><strong>Síntomas</strong></h4><ul><li>Usar la sintaxis que sea necesaria para romper el modelo de un lenguaje y poder así escribir código que nos resulte más familiar.</li><li>(<strong>POO</strong>) Tratar de llamar a funciones no estáticas o variables en clases no instanciadas y no ser capaces de comprender el porqué no funcionan como esperamos.</li><li>(<strong>POO</strong>) Escribir varias clases del tipo &#8216;xxxManager&#8217; que contengan cada una todos los mismos métodos de manipulación (aún con ligeras variaciones entre ellos).</li><li>(<strong>Relacional</strong>) Tratar una base de datos relacional como un mero objeto de almacenaje sobre el que luego realizaremos todas las relaciones, uniones, concatenaciones o filtrados en el lado del cliente.</li><li>(<strong>Funcional</strong>) Crear varias versiones del mismo algoritmo para manejar diferentes tipos u operadores en lugar de pasar funciones de alto nuvel a una implementación genérica.</li><li>(<strong>Funcional</strong>) Cachear manualmente los resultados de una función determinista en una plataforma que puede hacerlo de forma automática (como por ejemplo SQL y Haskell).</li><li>Recurrir al copiar y pegar desde el código de otro programa para lidiar con <a
href="http://es.wikipedia.org/wiki/Entrada/salida">I/O</a> y <a
href="http://en.wikipedia.org/wiki/Monad_(functional_programming)">Mónadas</a>.</li><li>(<strong>Declarativo</strong>) Asignar valores individuales en código imperativo en lugar de usar un <em><a
href="http://en.wikipedia.org/wiki/Data_binding">data-binding</a></em>.</li></ul><h4><strong>Remedios</strong></h4><p>Si la deficiencia de tus habilidades se debe a un aprendizaje o estudio inefectivo, entonces el remedio es tan sencillo como repasar los conceptos y profundizar en la especificación del lenguaje. <strong>No existe una forma más efectiva para aprender el modelo de un determinado lenguaje que iniciar un nuevo proyecto y obligarte a ti mismo a usar cada una de sus características</strong>, ya sean de forma inteligente o no. Incluso podemos crearnos un nuevo vocabulario con el que referirnos coloquialmente a cada una de esas nuevas funcionalidades para así asimilarlas de una forma más <em>natural</em>. Por ejemplo:</p><ul><li>Fase 1: POO son solo registros con métodos.</li><li>Fase 2: los métodos POO son solo funciones que ejecutan un mini programa con sus propias variables globales.</li><li>Fase 3: Las variables globales se llaman campos, algunos de los cuales pueden ser privados e invisibles desde fuera del mini programa.</li><li>Fase 4: La idea de tener elementos privados y públicos es esconder la implementación de los detalles y mostrar una interfaz más limpia. <strong>Y esto es la <a
href="http://es.wikipedia.org/wiki/Encapsulamiento_(inform%C3%A1tica)">encapsulación</a></strong>.</li><li>Fase 5: Encapsulación significa que la lógica de mi negocio no necesita de los detalles de la implementación para funcionar.</li></ul><p>Otro ejemplo para programación funcional:</p><ul><li>Fase 1: Programación funcional significa hacerlo todo encadenando <a
href="http://es.wikipedia.org/wiki/Algoritmo_determinista">funciones deterministas</a>.</li><li>Fase 2: Cuando las funciones son deterministas, el compilador puede predecir cuándo puede cachear un resultado, saltarse una evaluación o cuando es seguro detener una evaluación de forma prematura.</li><li>Fase 3: Para poder soportar Evaluaciones parciales o perezosas, el compilador necesita que las funciones estén definidas en términos de cómo transformar un simple parámetro en otra función. <strong>A esto lo llamamos Currying</strong>.</li><li>Fase 4: Algunas veces, el compilador puede hacer Currying por mi.</li><li>Fase 5: Al permitir al compilador trabajar en los detalles, yo puedo escribir programas que describan <em>qué</em> es lo que quiero en lugar del <em>cómo</em>.</li></ul><h2>3. Habilidades deficiente para investigar / Conocimiento pobre de las características de la plataforma</h2><p>Los lenguajes modernos y los <em>frameworks</em> suelen venir con una increible cantidad de recursos y funcionalidades ya preparados para su uso. Plataformas como Java, .NET o Cocoa poseen listados tan largos que incluso un desarrollador con experiencia puede tardar años en asimilarlos. Sin embargo, <strong>un buen programador sabrá buscar una función preconstruida para cubrir una necesidad antes de lanzarse a programar una desde cero</strong>.</p><h4><strong>Síntomas</strong></h4><p>Éstos son solo indicativos del problema si éste persiste en el tiempo más allá de una fase razonable de aprendizaje.</p><ul><li>Reinventar or crear estructuras básicas que ya están presentes en el lenguaje de forma nativa.</li><li>Reinventar clases y funciones que ya están presenten en un framework de forma nativa.</li><li>Correos continuos del tipo &#8216;Enviame el código, por favor&#8217; a los foros de ayuda.</li><li>Solucionar una tarea aplicando un mayor número de funciones del que sería necesario si conocemos el lenguaje.</li><li>Usar de forma persistente técnicas antiguas cuando éstas han sido reemplazadas por otras modernas y más efectivas. Por ejemplo, continuar utilizando funciones delegadas en lugar de usar expresiones lambda.</li><li>Permanecer constantemente en nuestra zona de confort y resolver así problemas complejos utilizando primitivas.</li></ul><h4><strong>Remedios</strong></h4><p>Un programador no puede adquirir este tipo de conocimiento sin un lento aprendizaje. Sin embargo, se requiere de la habilidad para buscar información con un mínimo esfuerzo, lo cual puede significar que tenga que compartir escritorio con un grueso libro junto al teclado, o tener un segundo monitor dedicado a mostrar constantemente un navegador con resultados útiles sobre aquello en lo que se trabaja.</p><p>Para iniciarnos en el hábito de mejorar nuestras habilidades, una buena práctica es coger nuestro código antiguo y tratar de refactorizarlo hasta conseguir una reducción del orden de 10:1 en el número de instrucciones empleadas.</p><h2>4. Incapacidad para entender punteros</h2><p>Si no somos capaces de entender los <a
href="http://es.wikipedia.org/wiki/Puntero_(inform%C3%A1tica)">punteros</a>, el tipo de programas que somos capaces de escribir se reduce de forma considerable. El concepto de puntero es la llave que permite la creación de estructuras complejas de datos y APIs eficientes. Tendríamos aquí que tener en cuenta que existen lenguajes que manejan referencias en lugar de punteros los cuales, aunque actúan de una forma similar pero automatizando algunos aspectos, requieren de conocer el concepto en si mismo para elaborar estructuras eficientes.</p><h4><strong>Síntomas</strong></h4><ul><li>Incapacidad para crear una lista enlazada, o escribir un código que inserte / elimine nodos de una lista o un árbol sin peder datos.</li><li>Asignar grandes arrays para colecciones de longitud variable y mantener un contador separado con dicha longitud en lugar de utilizar una estructura dinámica de datos.</li><li>Incapacidad para encontrar o corregir los errores tras realizar operaciones aritméticas en punteros.</li><li>Hacer una copia del puntero, cambiar su valor en la copia y asumir que el puntero original continúa apuntando a su antiguo valor.</li><li>Ordenar una matriz de punteros realizando una comparación sobre sus propios valores.</li></ul><h4><strong>Remedios</strong></h4><p>&#8220;<em>Mi amigo José estaba alojado en alguna habitación del hotel pero yo no sabía en cuál. Como si que sabía dónde estaba nuestro amigo Alberto, llamé a su puerta y le pregunté si el conocía dónde se alojaba José; me contestó que no, pero si que sabía el número de habitación de otro de nuestros colegas, Miguel. Fui entonces a su habitación y le pregunté. Me dijo que José se alojaba en la 414. Tras agradecérselo, me dirigí a la habitación 414 y, efectivamente, allí estaba mi amigo.</em>&#8221;</p><p>Los punteros pueden describirse siguiendo varias metáforas igual que puede hacerse con las estructuras de datos. El ejemplo de arriba es solo una forma de ejemplificar la idea que hay detrás. Historias como esa, pueden resultar útiles para convertir especificaciones en estructuras mentales más fáciles de asimilar.</p><h2>5. Dificultad para ver a través de la recursión</h2><p>La idea de la <a
href="http://es.wikipedia.org/wiki/Recursi%C3%B3n">recursión</a> es sencilla de entender pero <strong>los programadores a menudo tienen problemas para imaginar el resultado de una operación recursiva mentalmente</strong>, o cómo un resultado complejo puede ser calculado a través de una función muy simple. Esto hace difícil diseñar una función recursiva efectiva porque tenemos problemas en <em>dibujarlas</em> primero en nuestra cabeza. <strong>A todo este conjunto de operaciones las llamamos <a
href="http://es.wikipedia.org/wiki/Algoritmo">algoritmia</a></strong>.</p><h4><strong>Síntomas</strong></h4><ul><li>Superposición de <a
href="http://es.wikipedia.org/wiki/Iteraci%C3%B3n">algoritmos iterativos</a> para soluciones que pueden alcanzarse de una forma sencilla y elegante con recursividad.</li><li>Funciones recursivas que comprueban el estado de la base tanto antes como después de cada llamada.</li><li>Funciones recursivas que no comprueban en ningún momento el estado/valor de la base.</li><li>Subrutinas recursivas que concatenan / suman una variable global.</li><li>Confusión entre qué pasa a una llamada recursiva como parámetro o llamadas recursivas que pasan un parámetro sin modificar en cada iteración.</li><li>Pensar que el número de iteraciones va a pasar como parámetro.</li></ul><h4><strong>Remedios</strong></h4><p>Ármate de paciencia y asume que vas a <a
href="http://es.wikipedia.org/wiki/Desbordamiento_de_pila">desbordar la pila</a> varias veces hasta dar con el resultado correcto. Comienza escribiendo código con una única base-condición que pase como parámetro a una función recursiva. Codificamos y ejecutamos el algoritmo. ¿Desbordamos? Pues modificamos la lógica y volvemos a probar. <strong>El objetivo es finalmente alcanzar una visión completa <em>del camino que recorren los datos</em> dentro de un algoritmo hasta el punto de que podamos seguir varios hilos de forma simultánea</strong>. Es costoso, pero se puede practicar.</p><h2>6. Desconfianza en el código</h2><h4><strong>Síntomas</strong></h4><ul><li>Escribir funciones del tipo <em>isNull</em>, <em>isNotNull</em>, <em>isFalse</em>&#8230;</li><li>Comprobar si un valor tipado como booleano se corresponde con algo diferente de <em>true</em> o <em>false</em>.</li></ul><h4><strong>Remedios</strong></h4><p>Estás tratando de aplicar tus conocimientos de un lenguaje (por ejemplo de tipado blando) a otro (de tipado duro)? Si no es así, volvemos al primer punto sobre la incapacidad de razonar sobre un código.</p><p>Muchos de estos posibles síntomas se relacionan más con una dependencia sobre <em>un código dentro de nuestra zona de confort</em> que con una incapacidad natural para razonar una estructura abstracta. <strong>El único remedio aquí puede ser el de concedernos más tiempo para familiarizarnos con el lenguaje y construir así un conocimiento sólido</strong>.</p><h2>Conclusión</h2><p>Todos los puntos anteriores deben tomarse como un mero recetario con el que medir nuestra mayor o menor habilidad con un lenguaje o nuestra mejor o peor comprensión sobre una determinada plataforma.</p><p>El análisis de Lawrence puede resultar muy útil cuando por ejemplo, estamos aprendiendo un nuevo sistema y queremos saber si estamos listos para aplicarlo sobre un entorno real de producción.</p><p>Sin embargo, como el autor resuelve más arriba, cuando nos enfrentamos a una tecnología nueva, el mejor aprendizaje es el que obtenemos iniciando un proyecto real y tratando de superar las dificultades reales que surgen.</p><p>Finalmente, un acceso fluido a la información, la constancia y el no tener miedo a los errores, constituyen la clave para no quedarnos en el camino.</p><p>El resto del artículo, lo tenéis <a
href="http://www.yacoset.com/Home/signs-that-you-re-a-bad-programmer">aquí</a>.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=1961&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/10/26/signos-de-que-eres-un-mal-desarrollador/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Ordenación básica de datos en Javascript</title><link>http://www.etnassoft.com/2011/10/17/ordenacion-basica-de-datos-en-javascript/</link> <comments>http://www.etnassoft.com/2011/10/17/ordenacion-basica-de-datos-en-javascript/#comments</comments> <pubDate>Mon, 17 Oct 2011 07:07:46 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[algoritmia]]></category> <category><![CDATA[algoritmos]]></category> <category><![CDATA[bubble sort]]></category> <category><![CDATA[complejidad ciclomática]]></category> <category><![CDATA[datos]]></category> <category><![CDATA[insertion sort]]></category> <category><![CDATA[rendimiento]]></category> <category><![CDATA[selection sort]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=1892</guid> <description><![CDATA[Introducción Cuando comenzamos a estudiar algoritmos, uno de los temas más recurrentes para ejemplificar la materia es la ordenación de datos. Básicamente se trata de, partiendo de una lista con elementos dispuestos al azar, encontrar la forma de procesarla para &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/10/17/ordenacion-basica-de-datos-en-javascript/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Cuando comenzamos a estudiar algoritmos, uno de los temas más recurrentes para ejemplificar la materia es la ordenación de datos. Básicamente se trata de, <strong>partiendo de una lista con elementos dispuestos al azar, encontrar la forma de procesarla para devolverla ordenada</strong>.</p><p>Para esto, existen varios tipos de algoritmos diferentes que resuelven el problema a través de distintos acercamientos; estudiarlos es una buena forma de entender cómo se diseñan y cómo se mide el rendimiento de los mismos según cada uno de los escenarios posibles en los que pueden aplicarse.</p><p>En este artículo, repasaremos tres métodos muy conocidos de ordenación diferentes: <em><strong>bubblesort</strong></em>, <em><strong>selectionsort</strong></em> e <em><strong>insertionsort</strong></em>.</p><p>Cada uno de estos tres algoritmos se resuelven por iteración y, ya que son muy sencillos de codificar, se los considera como <strong>métodos simples</strong>. Pasemos sin más a estudiar cada uno de ellos para descubrir cuál(es) es el más interesante a la hora de implementarlo en un proyecto.<span
id="more-1892"></span></p><h2>Preparando el terreno</h2><p>Por lo general, todos los algoritmos de ordenación funcionan de una forma similar. Toman una lista de elementos, en nuestro caso un <em>array</em>, <strong>comparan sus elementos siguiendo una estrategia definida y, según el resultado de dicha comparación, mueven los datos de un lugar a otro hasta conseguir una lista (<em>array</em>) final ordenado</strong>.</p><p>Teniendo en cuenta lo anterior, un punto clave de nuestros métodos será mover valores entre los índices del <em>array </em>que queremos ordenar<em>.</em> Es decir, <strong>necesitaremos una función para intercambiar los valores de un array entre dos posiciones dadas</strong>.</p><p>Como no tenemos en Javascript una función similar, crearemos una. Por seguir la convención, <strong>llamaremos a nuestra función <em>swap</em></strong> y aceptará tres parámetros: el array sobre el que actuamos y los índices de aquellos dos elememtos que queremos intercambiar. Su codificación es muy simple:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * @function
 * @name swap
 * @description Swap two elements in an array
 * @param {array} myArr The target array.
 * @param {int} indexOne The index of the first element to swap.
 * @param {int} indexTwo The index of the second element to swap.
 * @returns {array} The array with the two elements swapped.
 */</span>
<span style="color: #003366; font-weight: bold;">function</span> swap<span style="color: #009900;">&#40;</span>myArr<span style="color: #339933;">,</span> indexOne<span style="color: #339933;">,</span> indexTwo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> tmpVal <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span>indexOne<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  myArr<span style="color: #009900;">&#91;</span>indexOne<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span>indexTwo<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  myArr<span style="color: #009900;">&#91;</span>indexTwo<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> tmpVal<span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>He comentado la función siguiendo la convención <a
title="JSDoc" href="http://code.google.com/p/jsdoc-toolkit/">JSDoc</a> para que resulte más clara. Como podemos ver, no realizo comprobación de tipos ni si existen los índices que se pretenden intercambiar. No es el objetivo de este artículo.</p><p>Una rápida demostración de su funcionamiento sería:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'b'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'c'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'d'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> swap<span style="color: #009900;">&#40;</span> myArr<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;b&quot;, &quot;a&quot;, &quot;c&quot;, &quot;d&quot;]</span></pre></div></div><p>Nuestra función hace el trabajo que se le espera: ha tomado los índices 0 y 1 del <em>array</em> para devolver uno nuevo con esos valores intercambiados. Un poco más adelante, afinaremos esta función para que ofrezca un mejor rendimiento.</p><p>Estamos listos para comenzar a implementar nuestros métodos de ordenación de datos!</p><h2>Bubble Sort (u ordenamiento por burbuja)</h2><p>Imaginemos que estamos en un parque con nuestra familia y queremos hacer una foto en la que salgan todos. Decidimos que podemos ordenarlos según sus edades de tal modo que tengamos al más joven a la izquierda y al más mayor a la derecha. Sin embargo, como no les hemos dicho nada, se han colocado de forma aleatoria:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/familia-1.gif" alt="" title="familia-1" width="695" height="235" class="aligncenter size-full wp-image-1893" /></p><p>Para aplicar un ordenamiento de tipo burbuja a este conjunto de elementos, tenemos que prestar atención a las dos primeras personas de la izquierda. Le preguntamos a cada uno por su edad y, si la que está a la izquierda es mayor que la de su derecha, intercambiamos sus posiciones. En el caso contrario, no hacemos nada ya que se encontrarían ordenados de forma relativa entre ellos.</p><p>En nuestro ejemplo, la persona de la izquierda es mayor que la de su derecha por lo que tenemos que realizar el primer intercambio:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/familia-2.gif" alt="" title="familia-2" width="695" height="235" class="aligncenter size-full wp-image-1894" /></p><p>Ahora fijamos nuestra atención en la segunda y tercera posición para repetir el proceso anterior: preguntamos por sus edades e intercambiamos posición si fuera necesario. En nuestro ejemplo, no tenemos que realizar ahora ningún intercambio, por lo que avanzaríamos para comparar la tercera y cuarta posición entre ellas. De nuevo, están ya ordenados de forma relativa puesto que la persona de la derecha, es mayor que la de su izquierda.</p><p>Avanzamos sin alterar nada hasta comparar la cuarta persona con la quinta. Ahora si nos volvemos a encontrar con que la persona de la izquierda es mayor que la derecha, por lo que es necesario un nuevo intercambio:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/familia-3.gif" alt="" title="familia-3" width="695" height="235" class="aligncenter size-full wp-image-1895" /></p><p>Hemos completado una vuelta sobre nuestro conjunto y de momento estamos aún lejos de tenerlo ordenado. Sin embargo, si que hemos conseguido algo importante: <strong>el elemento de la derecha está ya ubicado en su posición final</strong>; es decir, que como si de una burbuja se tratase, el elemento más grande (en este caso la persona más mayor) ha ido bullendo hasta su posición final.</p><p>El siguiente paso, <strong>sería volver a repetir el proceso ignorando la persona (el elemento) que está a la derecha del conjunto</strong> (puesto que ya está en su posición final).</p><p>Comparamos ahora la dos primeras posiciones y observamos que están ya ordenadas, por lo que pasamos directamente a comparar la segunda con la tercera posición. De nuevo tenemos los elementos ordenados de forma relativa entre ellos por lo que pasariamos evaluar la tercera y cuarta posición.</p><p>Llegados a ese punto, observamos que la persona de la izquierda es mayor que la de su derecha, por lo que intercambiamos posiciones obteniendo:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/familia-4.gif" alt="" title="familia-4" width="695" height="235" class="aligncenter size-full wp-image-1896" /></p><p>Hemos completado la segunda vuelta; comenzamos de nuevo e ignoramos ahora los dos últimos elementos. Finalmente, tras todas las iteraciones posibles, obtenemos:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/familia-5.gif" alt="" title="familia-5" width="695" height="235" class="aligncenter size-full wp-image-1897" /></p><p>Una vez que hemos comprendido cómo funciona, es hora de implementarlo en código.</p><p>La idea tras este algoritmo es que,<strong> a cada iteración por el conjunto, un elemento es llevado hasta su posición final</strong> y tiene que ser por lo tanto ignorado en las siguientes. Esto se traduce en que, a cada paso, se debe compara un elemento menos que en el anterior. Si <em>N</em> es el número de items en la lista, entonces en la primera iteración necesitamos comparar <em>N &#8211; 1</em>; en la segunda, <em>N &#8211; 2</em>, y así sucesivamente. Este tipo de códigos basado en bucles dependientes se resuelven muy fácilmente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> bubbleSort<span style="color: #009900;">&#40;</span>myArr<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> size <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> pass <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> pass <span style="color: #339933;">&lt;</span> size<span style="color: #339933;">;</span> pass<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// outer loop</span>
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> left <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> left <span style="color: #339933;">&lt;</span> <span style="color: #009900;">&#40;</span>size <span style="color: #339933;">-</span> pass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> left<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// inner loop</span>
      <span style="color: #003366; font-weight: bold;">var</span> right <span style="color: #339933;">=</span> left <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>left<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> myArr<span style="color: #009900;">&#91;</span>right<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        swap<span style="color: #009900;">&#40;</span>myArr<span style="color: #339933;">,</span> left<span style="color: #339933;">,</span> right<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>El código anterior, resulta muy sencillo de seguir. Un bucle <em>externo</em> recorre nuestro array tantas veces como elementos tenga menos uno. El bucle <em>interno</em> compara cada uno de los valores que encuentra (<em>left</em>) con aquel que inmediatamente posterior (<em>right</em>). Si <em>left</em> es mayor que <em>right</em>, se intercambia la posición y se continúa con el siguiente par.</p><p>Comprobamos nuestro código anterior con un array simple:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'f'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'c'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'e'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'b'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> bubbleSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;]</span></pre></div></div><p>La función nos devuelve nuestro array ordenado aunque, como seguramente intuimos, es probable que estemos realizano un alto número de iteraciones para ello&#8230;</p><p>Más adelante, mediremos el rendimiento de este algoritmo para compararlo con los dos restantes.</p><h2>Selection sort (u ordenamiento por selección)</h2><p>Imaginemos que tenemos una estanteria llena de libros de diferente tamaño (altura). Como no hemos seguido ningún criterio a la hora de colocarlos, están dispuestos de forma aleatoria y nos gustaría cambiar esto. Querríamos tenerlos colocados según su tamaño de tal modo que en el extremo izquierdo tuviéramos al más alto y en el derecho al más bajo.</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/estanteria-1.gif" alt="" title="estanteria-1" width="695" height="370" class="aligncenter size-full wp-image-1898" /></p><p>Sin embargo, son libros pesados y no parece interesante estar desplazándolos uno a uno como en el caso anterior. Lo ideal sería revisar todos los libros, seleccionar el siguiente según el orden que hemos establecido y colocarlo directamente en su posición final. <strong>Esta <em>selección</em> que da nombre al algoritmo permite tomar un elemento y desplazarlo en un único movimiento a su posición definitiva</strong>.</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/estanteria-2.gif" alt="" title="estanteria-2" width="695" height="370" class="aligncenter size-full wp-image-1899" /></p><p>En varias ocasiones, mientras escaneamos los libros, encontraremos que éstos están ya en su posición final y que no es necesario moverlos. También notaremos que tras cada movimiento, el conjunto de libros ordenados crece mientras que el de los desordenados disminuye lo que muestra el patrón que permite concluir el proceso.</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/estanteria-3.gif" alt="" title="estanteria-3" width="695" height="370" class="aligncenter size-full wp-image-1900" /></p><p>La secuencia completa para ordenar el resto de los libros sería el siguiente:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/estanteria-4.gif" alt="" title="estanteria-4" width="695" height="469" class="aligncenter size-full wp-image-1901" /></p><p>Como hemos comentado más arriba, en este tipo de ordenaciones, a diferencia de lo que ocurre con el método de burbuja, podemos encontrarnos continuamente con que un elemento ya está ordenado y no requiere de ese intercambio. Para ahorrar ese paso, modificaremos ligeramente la función <em>swap</em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> swap<span style="color: #009900;">&#40;</span>myArr<span style="color: #339933;">,</span> indexOne<span style="color: #339933;">,</span> indexTwo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> indexOne <span style="color: #339933;">==</span> indexTwo <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #003366; font-weight: bold;">var</span> tmpVal <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span>indexOne<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  myArr<span style="color: #009900;">&#91;</span>indexOne<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span>indexTwo<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  myArr<span style="color: #009900;">&#91;</span>indexTwo<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> tmpVal<span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Ahora estamos comprobando que las posiciones a intercambiar no sean la misma y, por tanto, estemos realizando una operación inútil.</p><p>La implementación del <em>selection sort</em> se construye a partir de un buble <em>externo</em> y otro <em>interno</em>, como en el anterior, pero con sutiles diferencias.</p><p>En primer lugar, el exterior recorre los valores entre cero y <em>N-2</em> en lugar de entre 1 y <em>N-1</em>. Aunque en realidad se trate finalmente del mismo número de pasos (<em>N-1</em>), <strong>operamos directamente sobre los <em>slots</em> para enviar ahí el valor correcto en cada una de las iteraciones</strong>. Por ejemplo, en el primer paso, nuestro objetivo es desplazar el elemento correcto hasta la posición cero; en el segundo, nuestro objetivo es rellenar la posición 1, y así sucesivamente.</p><p>De nuevo, necesitamos un número de iteraciones <em>N-1</em> puesto que tras cada ciclo, tendremos un elemento ubicado en su posición definitiva que podemos ignorar.</p><p>El código sería el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> selectionSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> size <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> slot <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> slot <span style="color: #339933;">&lt;</span> size <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> slot <span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// outer loop</span>
    <span style="color: #003366; font-weight: bold;">var</span> smallest <span style="color: #339933;">=</span> slot<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> check <span style="color: #339933;">=</span> slot <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> check <span style="color: #339933;">&lt;</span> size<span style="color: #339933;">;</span> check<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// inner loop</span>
      <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>check<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&lt;</span> myArr<span style="color: #009900;">&#91;</span>smallest<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        smallest <span style="color: #339933;">=</span> check<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    swap<span style="color: #009900;">&#40;</span> myArr<span style="color: #339933;">,</span> smallest<span style="color: #339933;">,</span> slot <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Lo probamos:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'f'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'c'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'e'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'b'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> selectionSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;]</span></pre></div></div><p>Como ocurría con el método anterior, un simple vistazo a la lógica del código nos puede poner sobre la pista de que quizá, hacemos más comparaciones de las que podrían ser necesarias. Eso por no entrar en la <a
title="Complejidad Ciclomática en Javascript. Concepto, ejemplos y herramientas de medición" href="http://www.etnassoft.com/2011/07/13/complejidad-ciclomatica-en-javascript-concepto-ejemplos-y-herramientas-de-medicion/">complejidad ciclomática</a> de tres niveles que presenta.</p><h2>Insertion Sort (u ordenación por inserción)</h2><p>Este algoritmo es muy similar al que utilizaríamos para ordenar las cartas en una mano de póquer a medida que nos las van sirviendo.</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/cartas-1.gif" alt="" title="cartas-1" width="695" height="288" class="aligncenter size-full wp-image-1902" /></p><p>La idea tras este concepto es la siguiente:</p><ul><li>Separamos según los palos en el siguiente orden: picas, tréboles, diamantes y corazones.</li><li>Por cada uno de esos palos, ordenamos de forma ascendiente: As, 2, 3, &#8230;, 9, 10, jota, reina y rey.</li></ul><p>La siguiente sucesión de imágenes nos mostraría el proceso de ordenación según fuéramos descubriendo cartas:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/cartas-2.gif" alt="" title="cartas-2" width="695" height="288" class="aligncenter size-full wp-image-1903" /></p><p>Inicialmente se tiene un solo elemento, que obviamente es un conjunto ordenado. Después, cuando hay <em>K</em> elementos ordenados de menor a mayor, se toma el elemento <em>K + 1</em> y se compara con todos aquellos ya ordenados, deteniéndose cuando se encuentra uno menor (todos los elementos mayores han sido desplazados una posición a la derecha). En este punto se insertaría el elemento <em>K + 1</em> desplazándose al resto.</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/cartas-3.gif" alt="" title="cartas-3" width="695" height="288" class="aligncenter size-full wp-image-1904" /></p><p>Avanzando en el ejemplo anterior, la siguiente carta se ordenaría siguiendo el mismo criterio:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/cartas-4.gif" alt="" title="cartas-4" width="695" height="288" class="aligncenter size-full wp-image-1905" /></p><p>El resto de la secuencia sería:</p><p><img
src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/10/cartas-5.gif" alt="" title="cartas-5" width="695" height="434" class="aligncenter size-full wp-image-1906" /></p><p>El código sería el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> insertionSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> size <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">,</span>
      slot<span style="color: #339933;">,</span>
      tmp<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">&lt;</span> size<span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// outer loop     </span>
    tmp <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span> slot <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> slot <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">&amp;&amp;</span> myArr<span style="color: #009900;">&#91;</span>slot<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> tmp<span style="color: #339933;">;</span> slot<span style="color: #339933;">--</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// inner loop</span>
      myArr<span style="color: #009900;">&#91;</span> slot <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> myArr<span style="color: #009900;">&#91;</span>slot<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    myArr<span style="color: #009900;">&#91;</span> slot <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> tmp<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>Y la comprobación de rigor:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'f'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'d'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'c'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'e'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'b'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> insertionSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;]</span></pre></div></div><p>Es cierto que este código es más difícil de seguir a simple vista y quizá no seamos capaces de advertir qué nivel de complejidad presenta. Pero no hay problema; ha llegado el momento de medir cada uno de los métodos anteriores y comparar los resultados.</p><h2>Comparando los algoritmos de ordenación básicos</h2><p>Una vez que hemos presentado algunos de estos algoritmos básicos, <strong>vamos a analizar su rendimiento de un modo práctico</strong>. Esta comparación no será definitiva en tanto a qué método escoger independientemente del escenario, sino que supone un ejemplo de cómo implementar un sistema de métrica sencillo sobre un código a evaluar.</p><p>Para ello, debemos contemplar los tres escenarios clave a la hora de medir un algoritmo de ordenación:</p><ul><li>Todos los datos se encuentran de partida ya ordenados (el mejor de los casos).</li><li>Todos los datos se encuentran de partida ya ordenados pero en sentido inverso al deseado (el peor de los casos).</li><li>Los datos se encuentran dispuestos en cualquier orden (el caso más habitual).</li></ul><p>Para simular cada uno de estos estados, crearemos 3 listas diferentes de 1000 elementos sobre la que aplicaremos nuestros algoritmos y sus mediciones:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> TEST_SIZE <span style="color: #339933;">=</span> <span style="color: #CC0000;">1000</span><span style="color: #339933;">,</span>
    sortedArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    reverseArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    randomArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> x0<span style="color: #339933;">;</span> x<span style="color: #339933;">--</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  reverseArr.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>x<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> x</pre></div></div><p>Con nuestros <em>arrays</em> preparados, <strong>nos falta implementar algún tipo de contador</strong> para medir el número de iteraciones que realizan nuestros algoritmos. Para ello, nos valdremos de una variable <em>contadora</em> que introduciremos en el interior (<em>inner loop</em>) de cada una de nuestras funciones:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> counter <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> bubbleSort<span style="color: #009900;">&#40;</span>myArr<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> size <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
  counter <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> pass <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> pass <span style="color: #339933;">&lt;</span> size<span style="color: #339933;">;</span> pass<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// outer loop</span>
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> left <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> left <span style="color: #339933;">&lt;</span> <span style="color: #009900;">&#40;</span>size <span style="color: #339933;">-</span> pass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> left<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// inner loop       </span>
      <span style="color: #003366; font-weight: bold;">var</span> right <span style="color: #339933;">=</span> left <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
      counter<span style="color: #339933;">++;</span>
      <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>left<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> myArr<span style="color: #009900;">&#91;</span>right<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        swap<span style="color: #009900;">&#40;</span>myArr<span style="color: #339933;">,</span> left<span style="color: #339933;">,</span> right<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Bubble Sort: '</span><span style="color: #339933;">,</span> counter <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> selectionSort<span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> size <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
  counter <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> slot <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> slot <span style="color: #339933;">&lt;</span> size <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> slot <span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// outer loop</span>
    <span style="color: #003366; font-weight: bold;">var</span> smallest <span style="color: #339933;">=</span> slot<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> check <span style="color: #339933;">=</span> slot <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> check <span style="color: #339933;">&lt;</span> size<span style="color: #339933;">;</span> check<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// inner loop</span>
      counter<span style="color: #339933;">++;</span>
      <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>check<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&lt;</span> myArr<span style="color: #009900;">&#91;</span>smallest<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        smallest <span style="color: #339933;">=</span> check<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    swap<span style="color: #009900;">&#40;</span> myArr<span style="color: #339933;">,</span> smallest<span style="color: #339933;">,</span> slot <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  console.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Selection  Sort: '</span><span style="color: #339933;">,</span> counter <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> myArr<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> insertionSort<span style="color: #009900;">&#40;</span> vector <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> innerCounter <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  counter <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> vector.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> temp <span style="color: #339933;">=</span> vector<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> j <span style="color: #339933;">=</span> i<span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
    counter<span style="color: #339933;">++;</span>
    <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">&amp;&amp;</span> vector<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> temp<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      innerCounter<span style="color: #339933;">++;</span>
      vector<span style="color: #009900;">&#91;</span>j <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> vector<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      j<span style="color: #339933;">--;</span>
    <span style="color: #009900;">&#125;</span>
    vector<span style="color: #009900;">&#91;</span>j<span style="color: #339933;">+</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> temp<span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  console.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Insertion Sort: '</span><span style="color: #339933;">,</span> innerCounter <span style="color: #339933;">||</span> counter <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> vector<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>El contador de la función <em>insertionSort</em> es diferente a los otros dos ya que aquí puede darse el caso (improbable) de que no se entre en el bucle interno. Esto pasaría, efectivamente, si la lista que manejáramos correspondiese a la que hemos etiquietado como el &#8216;mejor caso&#8217;; es decir, donde todos sus elementos estuviesen ya ordenados.</p><p>Con nuestros contadores ya preparados, solo tenemos que ejecutar los algoritmos de ordenación sobre cada uno de los arrays que hemos preparado antes. El resultado que obtenemos es el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">bubbleSort<span style="color: #009900;">&#40;</span> sortedArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
bubbleSort<span style="color: #009900;">&#40;</span> reverseArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
bubbleSort<span style="color: #009900;">&#40;</span> randomArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
&nbsp;
selectionSort<span style="color: #009900;">&#40;</span> sortedArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
selectionSort<span style="color: #009900;">&#40;</span> reverseArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
selectionSort<span style="color: #009900;">&#40;</span> randomArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
&nbsp;
insertionSort<span style="color: #009900;">&#40;</span> sortedArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 999</span>
insertionSort<span style="color: #009900;">&#40;</span> reverseArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 499500</span>
insertionSort<span style="color: #009900;">&#40;</span> randomArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 257994</span></pre></div></div><p>Tenemos varios datos interesantes en estas mediciones:</p><ul><li>La ordenación por burbuja y por selección relaizan siempre el mismo número de comparaciones.</li><li>El número de comparaciones que requieren la ordenación por burbujas y por selección es independiente del estado de los datos de entrada.</li><li>El número de comparaciones requeridas por el algoritmo de inserción es muy sensible al estado inicial de los datos. En el peor de los casos, requiere el mismo número de comparaciones que los otros; en el mejor, le basta con una iteración menos que el número total de elementos que contiene el <em>array</em>.</li></ul><p>Lo más importante de los datos anteriores es que<strong> tanto la burbuja como la selección son insensibles al estado de los datos</strong>. Pueden considerarse así como algoritmos de &#8220;fuerza bruta&#8221; en oposición a la inserción que puede describirse como adaptable: si precisa menos trabajo, realiza menos trabajo.</p><h2>Conclusión</h2><p>Tras los datos arrojados por los métodos anteriores, podemos hacernos una idea de como rinden estos métodos básicos que hemos presentado. Sin embargo, hay que tener cuidado con no extraer más conclusiones de la cuenta.</p><p>Para realmente conocer la diferencia entre sus comportamientos, <strong>deberíamos también medir diferentes escenarios como cuánto afecta el número de objetos que componen cada lista de forma precisa (esto sería la escalabilidad) y el tiempo de ejecución real de cada sistema de ordenación (el coste de CPU)</strong>.</p><p>Como idea final, podemos obtener que, <strong>por lo general, un algoritmo de inserción realiza, como mínimo, un trabajo similar al de la burbuja o la selección</strong>. Para la gran mayoría de escenarios, sin embargo,<strong> su rendimiento se demuestra muy superior</strong> y, por tanto, resulta una opción mejor.</p><p>Para la segunda parte de este artículo, estudiaremos algoritmos avanzados como el <strong><em>shellsort</em></strong>, el célebre <strong><em>quicksort</em></strong> o el potente <strong><em>mergesort</em></strong>. Al igual que con los básicos, realizaremos métricas sobre su rendimiento para tener una primera impresión sobre cuál es el método más adecuado para cada uno de los posibles escenarios que pueden presentarse.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=1892&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/10/17/ordenacion-basica-de-datos-en-javascript/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>Cómo comparar objetos y arrays en Javascript</title><link>http://www.etnassoft.com/2011/10/05/como-comparar-objetos-y-arrays-en-javascript/</link> <comments>http://www.etnassoft.com/2011/10/05/como-comparar-objetos-y-arrays-en-javascript/#comments</comments> <pubDate>Wed, 05 Oct 2011 07:13:45 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[arrays]]></category> <category><![CDATA[asserts]]></category> <category><![CDATA[comparación]]></category> <category><![CDATA[igualdad]]></category> <category><![CDATA[objetos]]></category> <category><![CDATA[tdd]]></category> <category><![CDATA[test unitarios]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=1826</guid> <description><![CDATA[Introducción Es muy frecuente que, durante la etapa de debug de un código, tengamos que realizar diversas comparaciones entre objetos. Por ejemplo, uno de los métodos más recurrentes cuando realizamos TDD es el assertEquals donde pasamos dos términos y esperamos &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/10/05/como-comparar-objetos-y-arrays-en-javascript/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>Es muy frecuente que, durante la etapa de debug de un código, tengamos que realizar diversas comparaciones entre objetos. Por ejemplo, uno de los métodos más recurrentes <a
href="http://www.etnassoft.com/category/tdd-2/">cuando realizamos TDD</a> es el <em>assertEquals</em> donde pasamos dos términos y esperamos comprobar si ambos son iguales.</p><p>Sin embargo, pese a que cuando comparamos cadenas y números no hay ningún problema, no ucurre lo mismo cuando nos enfrentamos a objetos o arrays. Un ejemplo de resultados <em>poco intuitivos</em> son los siguientes:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> foo <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello World'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">==</span> <span style="color: #009900;">&#123;</span> foo <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello World'</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> foo <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello World'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">===</span> <span style="color: #009900;">&#123;</span> foo <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello World'</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// false</span></pre></div></div><p>Como podemos ver, <a
title="Operadores de igualdad en Javascript" href="http://www.etnassoft.com/2011/01/24/operadores-de-igualdad-en-javascript/">ni la comparación simple ni la estricta</a>, resultan útiles a la hora de trabajar con objetos y arrays. Como cabe esperar, si la estructura fuera más complicada, con más elementos anidados, el resultado sería siendo el mismo.<span
id="more-1826"></span></p><h2>Preparando el terreno</h2><p>Para conseguir una comparación estricta (o como algunos frameworks lo llaman <em>profunda</em>), <strong>tenemos que crear una función personalizada</strong>. Y para ello, <strong>no existe ningún otro método que no se base en la fuerza bruta</strong>: hay que iterar por cada método o valor de nuestros objetos para poder realizar la comparación.</p><p>Para facilitar el trabajo, vamos a recurrir a uan vieja conocida: <a
title="Cómo obtener el tipo de datos preciso de una variable en Javascript" href="http://www.etnassoft.com/2011/08/16/como-obtener-el-tipo-de-datos-preciso-de-una-variable-en-javascript/">la función toType()</a> que vimos en un artículo anterior. Gracias a este pequeño <em>snippet</em>, podemos determinar de forma precisa el tipo de dato de de un objeto superando así las capacidades del <a
href="https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof">operador nativo <em>typeof</em></a>.</p><p>El código de dicha función es el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> toType <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> obj <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// consider: typeof null === object</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>obj <span style="color: #339933;">===</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;null&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> type <span style="color: #339933;">=</span> Object.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">toString</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\[object\s(.*)\]$/</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>type<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'Number'</span><span style="color: #339933;">:</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>isNaN<span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;nan&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;number&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'String'</span><span style="color: #339933;">:</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'Boolean'</span><span style="color: #339933;">:</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'Array'</span><span style="color: #339933;">:</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'Date'</span><span style="color: #339933;">:</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'RegExp'</span><span style="color: #339933;">:</span>
  <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'Function'</span><span style="color: #339933;">:</span>
    <span style="color: #000066; font-weight: bold;">return</span> type.<span style="color: #660066;">toLowerCase</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> obj <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;object&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;object&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000066; font-weight: bold;">return</span> undefined<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div><p>Si prestamos atención, este código es ligeramente diferente al que aparece en el citado artículo: <strong>se ha mejorado la detección para los casos <em>NaN</em> y <em>Number</em></strong>; por lo demás, su funcionamiento no ha variado:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> toType<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// array</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> toType<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> foo<span style="color: #339933;">:</span> <span style="color: #3366CC;">'1'</span> <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// object</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> toType<span style="color: #009900;">&#40;</span> undefined <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// undefined</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> toType<span style="color: #009900;">&#40;</span> NaN <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// nan</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> toType<span style="color: #009900;">&#40;</span> <span style="color: #009966; font-style: italic;">/ \s+/</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// regexp</span></pre></div></div><h2>Creando la función &#8220;equals&#8221;</h2><p>Existen básicamente dos formas de implementar nuestra función: la primera es como tal, una función que acepte dos parámetros y nos devuelva un valor booleano con el resultado de la comparación. La segunda es como una extensión del <em>Object</em> mediante su prototipo para que esté siempre disponible independientemente del <em>scope</em> en el que nos encontremos.</p><p>Según lo anterior, invocariamos nuestra función de las siguientes formas:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Normal function</span>
equals<span style="color: #009900;">&#40;</span> a<span style="color: #339933;">,</span> b <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Prototype extend</span>
a.<span style="color: #660066;">equals</span><span style="color: #009900;">&#40;</span> b <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Personalmente, siempre prefiero la primera opción ya que, aunque más lenta (dependiendo de dónde se invoque hay que remontar los scopes necesarios hasta alcanzar su definición), es más segura: no hay problemas con posibles colisiones ya sean en el intérprete o con bibliotecas de terceros.</p><p>La función completa se muestra a continuación y ha sido extraída del framework <a
href="http://docs.jquery.com/Qunit">QUnit</a> que <a
title="QUnit, testeando nuestras aplicaciones Javascript." href="http://www.etnassoft.com/2011/02/01/qunit-testeando-nuestras-aplicaciones-javascript/">ya estudiamos en su día</a>; la autoría corresponde a <a
href="http://twitter.com/#!/prathe">Philippe Rathé</a>. El código está lo suficientemente comentado para ser autoexplicativo:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> equals <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> innerEquiv<span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// the real equiv function</span>
  <span style="color: #003366; font-weight: bold;">var</span> callers <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// stack to decide between skip/abort functions</span>
  <span style="color: #003366; font-weight: bold;">var</span> parents <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// stack to avoiding loops from circular referencing</span>
  <span style="color: #006600; font-style: italic;">// Call the o related callback with the given arguments.</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">function</span> bindCallbacks<span style="color: #009900;">&#40;</span>o<span style="color: #339933;">,</span> callbacks<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> prop <span style="color: #339933;">=</span> toType<span style="color: #009900;">&#40;</span>o<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>prop<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>toType<span style="color: #009900;">&#40;</span>callbacks<span style="color: #009900;">&#91;</span>prop<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;function&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> callbacks<span style="color: #009900;">&#91;</span>prop<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>callbacks<span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> callbacks<span style="color: #009900;">&#91;</span>prop<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// or undefined</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> callbacks <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// for string, boolean, number and null</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">function</span> useStrictEquality<span style="color: #009900;">&#40;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #000066; font-weight: bold;">instanceof</span> a.<span style="color: #660066;">constructor</span> <span style="color: #339933;">||</span> a <span style="color: #000066; font-weight: bold;">instanceof</span> b.<span style="color: #660066;">constructor</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// to catch short annotaion VS 'new' annotation of a</span>
        <span style="color: #006600; font-style: italic;">// declaration</span>
        <span style="color: #006600; font-style: italic;">// e.g. var i = 1;</span>
        <span style="color: #006600; font-style: italic;">// var j = new Number(1);</span>
        <span style="color: #000066; font-weight: bold;">return</span> a <span style="color: #339933;">==</span> b<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> a <span style="color: #339933;">===</span> b<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #3366CC;">&quot;string&quot;</span><span style="color: #339933;">:</span> useStrictEquality<span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;boolean&quot;</span><span style="color: #339933;">:</span> useStrictEquality<span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;number&quot;</span><span style="color: #339933;">:</span> useStrictEquality<span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;null&quot;</span><span style="color: #339933;">:</span> useStrictEquality<span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #339933;">:</span> useStrictEquality<span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #3366CC;">&quot;nan&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> isNaN<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #3366CC;">&quot;date&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> QUnit.<span style="color: #660066;">toType</span><span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;date&quot;</span> <span style="color: #339933;">&amp;&amp;</span> a.<span style="color: #660066;">valueOf</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> b.<span style="color: #660066;">valueOf</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #3366CC;">&quot;regexp&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> QUnit.<span style="color: #660066;">toType</span><span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;regexp&quot;</span> <span style="color: #339933;">&amp;&amp;</span> a.<span style="color: #660066;">source</span> <span style="color: #339933;">===</span> b.<span style="color: #660066;">source</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #006600; font-style: italic;">// the regex itself</span>
        a.<span style="color: #660066;">global</span> <span style="color: #339933;">===</span> b.<span style="color: #660066;">global</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #006600; font-style: italic;">// and its modifers</span>
        <span style="color: #006600; font-style: italic;">// (gmi) ...</span>
        a.<span style="color: #660066;">ignoreCase</span> <span style="color: #339933;">===</span> b.<span style="color: #660066;">ignoreCase</span> <span style="color: #339933;">&amp;&amp;</span> a.<span style="color: #660066;">multiline</span> <span style="color: #339933;">===</span> b.<span style="color: #660066;">multiline</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">// - skip when the property is a method of an instance (OOP)</span>
      <span style="color: #006600; font-style: italic;">// - abort otherwise,</span>
      <span style="color: #006600; font-style: italic;">// initial === would have catch identical references anyway</span>
      <span style="color: #3366CC;">&quot;function&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> caller <span style="color: #339933;">=</span> callers<span style="color: #009900;">&#91;</span>callers.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> caller <span style="color: #339933;">!==</span> Object <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000066; font-weight: bold;">typeof</span> caller <span style="color: #339933;">!==</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #3366CC;">&quot;array&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">,</span> j<span style="color: #339933;">,</span> loop<span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> len<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// b could be an object literal here</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>toType<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;array&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        len <span style="color: #339933;">=</span> a.<span style="color: #660066;">length</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>len <span style="color: #339933;">!==</span> b.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// safe and faster</span>
          <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// track reference to avoid circular references</span>
        parents.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> len<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          loop <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;</span> parents.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>parents<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
              loop <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// dont rewalk array</span>
            <span style="color: #009900;">&#125;</span>
          <span style="color: #009900;">&#125;</span>
          <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>loop <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>innerEquiv<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parents.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
          <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        parents.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
      <span style="color: #3366CC;">&quot;object&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">,</span> j<span style="color: #339933;">,</span> loop<span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> eq <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// unless we can proove it</span>
        <span style="color: #003366; font-weight: bold;">var</span> aProperties <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
          bProperties <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// collection of</span>
        <span style="color: #006600; font-style: italic;">// strings</span>
        <span style="color: #006600; font-style: italic;">// comparing constructors is more strict than using</span>
        <span style="color: #006600; font-style: italic;">// instanceof</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a.<span style="color: #660066;">constructor</span> <span style="color: #339933;">!==</span> b.<span style="color: #660066;">constructor</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// stack constructor before traversing properties</span>
        callers.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>a.<span style="color: #660066;">constructor</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">// track reference to avoid circular references</span>
        parents.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #000066; font-weight: bold;">in</span> a<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// be strict: don't ensures hasOwnProperty</span>
          <span style="color: #006600; font-style: italic;">// and go deep</span>
          loop <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;</span> parents.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>parents<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> loop <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// don't go down the same path</span>
            <span style="color: #006600; font-style: italic;">// twice</span>
          <span style="color: #009900;">&#125;</span>
          aProperties.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// collect a's properties</span>
          <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>loop <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>innerEquiv<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            eq <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
          <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        callers.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// unstack, we are done</span>
        parents.<span style="color: #660066;">pop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #000066; font-weight: bold;">in</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          bProperties.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// collect b's properties</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// Ensures identical properties name</span>
        <span style="color: #000066; font-weight: bold;">return</span> eq <span style="color: #339933;">&amp;&amp;</span> innerEquiv<span style="color: #009900;">&#40;</span>aProperties.<span style="color: #660066;">sort</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> bProperties.<span style="color: #660066;">sort</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  innerEquiv <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// can take multiple arguments</span>
    <span style="color: #003366; font-weight: bold;">var</span> args <span style="color: #339933;">=</span> Array.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">slice</span>.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span>arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>args.<span style="color: #660066;">length</span> <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// end transition</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">===</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// catch the most you can</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">===</span> <span style="color: #003366; font-weight: bold;">null</span> <span style="color: #339933;">||</span> b <span style="color: #339933;">===</span> <span style="color: #003366; font-weight: bold;">null</span> <span style="color: #339933;">||</span> <span style="color: #000066; font-weight: bold;">typeof</span> a <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;undefined&quot;</span> <span style="color: #339933;">||</span> <span style="color: #000066; font-weight: bold;">typeof</span> b <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;undefined&quot;</span> <span style="color: #339933;">||</span> toType<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> toType<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// don't lose time with error prone cases</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> bindCallbacks<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> callbacks<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>b<span style="color: #339933;">,</span> a<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">// apply transition with (1..n) arguments</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> args<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> arguments.<span style="color: #660066;">callee</span>.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> args.<span style="color: #660066;">splice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> args.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> innerEquiv<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Un rápido vistazo por el código nos muestra que se basa una comprobación sistemática de los argumentos aplicando a cada uno el algoritmo de comparación más adecuado.</p><p>Para el caso de los objetos y los arrays, el proceso pasa por iterarlos comparando si en cada paso los valores se correspondan con los esperados.</p><p>La función, al basarse en la fuerza bruta, <strong>puede resultar lenta cuando comparamos objetos muy complejos y anidados</strong>. Afortunadamente, el recorrido de circuito corto característico de Javascript permite salir inmediatamente de la función tras la primera comparación fallida evitando realizar las restantes.</p><h2>Conclusión</h2><p>A veces, los métodos y operadores nativos de Javascript no permiten efectuar algunas operaciones que podríamos considerar básicas. En este caso concreto, nos encontramos con la inconsistencia del lenguaje a la hora de comparar objetos y arrays en lo que sería algo trivial durante un desarrollo dirigido por tests.</p><p>Gracias al ejemplo anterior, podemos contar con una pieza de código reutilizable que puede sacarnos de un apuro en más de una ocasión.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=1826&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/10/05/como-comparar-objetos-y-arrays-en-javascript/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Estudiando el diseño de jQuery paso a paso (II Parte)</title><link>http://www.etnassoft.com/2011/09/28/estudiando-el-diseno-de-jquery-paso-a-paso-parte-2/</link> <comments>http://www.etnassoft.com/2011/09/28/estudiando-el-diseno-de-jquery-paso-a-paso-parte-2/#comments</comments> <pubDate>Wed, 28 Sep 2011 06:52:07 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[autoejecutable]]></category> <category><![CDATA[funciones]]></category> <category><![CDATA[modulo]]></category> <category><![CDATA[patrón]]></category> <category><![CDATA[patrones de diseño]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=1784</guid> <description><![CDATA[Introducción No tenía pensado hacer una continuación del anterior artículo &#8216;Estudiando el diseño de jQuery paso a paso&#8216; pero, a raíz de los comentarios de algunos usuarios, he visto interesante que continuemos profundizando en esta arquitectura para comprender mejor cómo &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/09/28/estudiando-el-diseno-de-jquery-paso-a-paso-parte-2/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>No tenía pensado hacer una continuación del anterior artículo &#8216;<a
title="Estudiando el diseño de jQuery paso a paso" href="http://www.etnassoft.com/2011/09/12/estudiando-el-diseno-de-jquery-paso-a-paso/">Estudiando el diseño de jQuery paso a paso</a>&#8216; pero, a raíz de los comentarios de algunos usuarios, he visto interesante que continuemos profundizando en esta arquitectura para comprender mejor cómo construir nuestros propios frameworks o bibliotecas.</p><h2>Aplicando métodos por referencia</h2><p>Uno de los aspectos más interesantes en el uso de jQuery es <strong>la aplicación de sus métodos por referencia</strong>. Nosotros, en el ejercicio anterior, habíamos creado un objeto donde, para aplicar una funcionalidad concreta a una cadena, ésta se pasaba como argumento del correspondiente método:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'   Hola Mundo '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Hola Mundo</span></pre></div></div><p>Sin embargo, a la hora de trabajar con la API pública de nuestra biblioteca, <strong>resulta mucho más cómodo cuando la funcionalidad se aplica sobre un argumento asociado al objeto y no al método</strong>. Siguiendo el ejemplo anterior, la nueva propuesta de sintaxis sería:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'  Hola Mundo   '</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>De este modo, ganamos en legibilidad a la vez que abrimos las puertas a otros comportamientos interesantes que veremos más adelante.<br
/> <span
id="more-1784"></span><br
/> Para permitir este tipo de construcciones, tenemos que realizar varios cambios en nuestra biblioteca; modificaciones que van en la línea de lo que hacen otros frameworks y que nos permitirá conocer un poco mejor estas estructuras relativamente complejas del lenguaje.</p><p>Lo veremos a continuación en detalle pero, para ir poniéndonos sobre la pista, <strong>la idea general es permitir que nuestro objeto se comporte bien como una función o bien como un objeto tradicional según la forma en que sea invocado</strong>.</p><h2>El nuevo patrón</h2><p>Para este ejemplo, vamos a renombrar nuestro framework como &#8216;<em>Utils</em>&#8216; evitando así posibles colisiones con la biblioteca jQuery genuina. Por el mismo motivo, cambiaremos también el álias y utilizaremos &#8216;<em>$$</em>&#8216; (doble símbolo de dólar) como método abreviado para llamarla.</p><p>La estructura básica quedaría como sigue:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  window.<span style="color: #660066;">utils</span> <span style="color: #339933;">=</span> window.$$ <span style="color: #339933;">=</span> utils<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Por el momento no hemos realizado ningún cambio; recurrimos al patrón de módulo modificado donde asociamos directamente el objeto creado al ámbito global representado por <em>window</em>.</p><p>Ahora, para que los métodos que tengamos en nuestro framework puedan trabajar directamente con los argumentos del objeto general, tenemos que observar un detalle importante que se ve más claro cuando aislamos un caso de uso:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Hola Mundo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Nuestra biblioteca, así invocada, <strong>está funcionando realmente como una función a la que se le asigna un argumento, no como un objeto en el que buscamos un método</strong> (<em>$$.myMethod()</em>). Por lo tanto, nuestro framework tiene que comportarse como una función o como un objeto según sea el caso.</p><p>Para conseguir el primer objetivo, el que <em>utils</em> responda al comportamiento de una función, <strong>crearemos una en su interior que nos servirá de contenedor y que permitirá pasar los argumentos a los métodos que sean llamados a continuación</strong>. A esta nueva función la llamaremos <em>core</em> (núcleo) y la implementamos paso a paso de la siguiente forma:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> core <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #009966; font-style: italic;">/* ... */</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Methods goes here</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Return</span>
    <span style="color: #000066; font-weight: bold;">return</span> core<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  window.<span style="color: #660066;">utils</span> <span style="color: #339933;">=</span> window.$$ <span style="color: #339933;">=</span> utils<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><h2>Tenemos ahora un núcleo general</h2><p>Hemos creado un nuevo objeto, en realidad una función, que puede recibir sus correspondientes argumentos (en este caso de momento solo <em>args</em>). Si avanzamos hasta el final, vemos un <em>return</em> que devuelve directamente dicho objeto/función. De esta forma estamos haciendo que al escribir,</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Hola Mundo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p><strong>nuestro framework se comporte como una función normal que recoge parámetros</strong> (<em>&#8216;Hola Mundo&#8217;</em>). Tenemos ya una parte importante adelantada!</p><p>El siguiente paso es sencillo: como sabemos que el flujo de nuestro framework pasa ahora por <em>core</em> cuando utilizamos la fórmula anterior,<strong> podemos almacenar sus argumentos en una propiedad del objeto para recuperarla más adelante en los métodos</strong>.</p><p>El código para conseguir este paso puede parecer complejo a priori pero, una vez analizado con detenimiento, es en realidad muy simple:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> core <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">new</span> core.<span style="color: #660066;">fn</span>.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    core.<span style="color: #660066;">fn</span> <span style="color: #339933;">=</span> core.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      init<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        core._args <span style="color: #339933;">=</span> args<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> core<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Methods goes here</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Return</span>
    <span style="color: #000066; font-weight: bold;">return</span> core<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  window.<span style="color: #660066;">utils</span> <span style="color: #339933;">=</span> window.$$ <span style="color: #339933;">=</span> utils<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>La jugada es devolver desde <em>core</em>, con <em>return</em>, una nueva función que definimos un poco más adelante. Al utilizar la palabra reservada <em>new</em>, hay que recordar que estamos utilizando dicha función como constructor y que, en realidad, estamos creando un nuevo objeto con los atributos que la componen. De este modo, <strong>hemos convertido nuestra función inicial en un objeto que ahora acepta métodos</strong>.</p><p>En esta estructura, <em>init</em> nos sirve como <em>inicializador mejorado</em> del objeto final: desde aquí, podemos pasar tantos argumentos como necesitemos para, por ejemplo, preconfigurar varios atributos de nuestro objeto final. En este caso, para simplificar el ejercicio, solo pasamos aquello que nos está llegando desde la API pública ( es decir, lo que un usuario haya especificado mediante una sintaxis del tipo $$(&#8216;my string&#8217;).myMethod() ).</p><p><em>init</em> coge los argumentos y los asocia (guarda) en el mismo <em>core</em> como una nueva propiedad (<em>_args</em>) que será la que usaremos más adelante cuando tratemos los métodos. Finalmente, devuelve el mismo objeto pero ya modificado y listo para añadirle funcionalidad.</p><p><em>NOTA: </em>Al nombre de la propiedad le hemos añadido un guión bajo para indicar que se trata de un método <em>privado</em> (no accesible desde la API pública); una convención útil cuando trabajamos con objetos grandes.</p><h2>Los métodos de la API pública</h2><p>Con nuestros elementos ya accesibles, solo tenemos que comenzar a añadir métodos que los recojan y modifiquen de alguna manera. Como ejemplo, retomaremos de los ejercicios anteriores nuestra función <em>trim()</em> para eliminar los espacios al pricipio y final de una cadena dada.</p><p><em>NOTA: Ya que el código necesario para llevar a cabo esta funcionalidad es muy sencillo, permite que nos concentremos mejor en cómo se implementa en lugar de en cómo trabaja.</em></p><p><strong>Para que los métodos sean accesibles éstos deben ser ahora parte del <em>core</em></strong>, por lo que únicamente tenemos que extender dicho objeto usando el sistema tradicional:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #003366; font-weight: bold;">var</span> core <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">new</span> core.<span style="color: #660066;">fn</span>.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    core.<span style="color: #660066;">fn</span> <span style="color: #339933;">=</span> core.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      init<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        core._args <span style="color: #339933;">=</span> args<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> utils<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Methods goes here</span>
    core.<span style="color: #660066;">trim</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      core._args <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> core._args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">return</span> str.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\s+|\s+$/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Return</span>
    <span style="color: #000066; font-weight: bold;">return</span> core<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  window.<span style="color: #660066;">utils</span> <span style="color: #339933;">=</span> window.$$ <span style="color: #339933;">=</span> utils<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Como vemos, la idea es que cada método que implementemos extienda al núcleo con una nueva función. <strong>En este caso, es interesante observar que podemos recoger un argumento</strong>. Esto es así para conservar la <em>compatibilidad con la forma anterior</em>. Es decir, que podemos obtener el mismo resultado tanto pasándole un argumento al objeto general como al método en particular:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'  Hola Mundo  '</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span>  <span style="color: #006600; font-style: italic;">// Retrocompatibilidad con la forma anterior.</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> $$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'  Hola Mundo  '</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// Nueva invocación por declaración.</span></pre></div></div><p>Para que el framework sepa de dónde tomar el parámetro, hemos añadido un condicional:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">core._args <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> core._args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Esto lo que hace es preguntar si existen argumentos ya cacheados. En caso de que existan, los tomamos como argumentos; si no, buscamos aquellos pasados directamente al método <em>trim()</em>.</p><p>La línea de código anterior, aunque parece compleja, es un simple <em>shotcut</em> de las siguientes:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> core._args <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  str <span style="color: #339933;">=</span> core._args
<span style="color: #009900;">&#125;</span></pre></div></div><p>La sintaxis propuesta funciona porque, como hemos mencionado en varias ocasiones, <strong>Javascript es un lenguaje de <em>circuito corto</em></strong> (o cortocircuito). Esto quiere decir que cuando realizamos comparaciones lógicas (booleanas), los términos se evalúan de izquierda a derecha rompiéndose inmediatamente la secuencia tras la primera disconformidad. En este condicional, si la primera parte de la expresión es correcta (si existe <em>core._args</em>), se evalúa el siguiente término. Dicho término (<em>str = core._args)</em> es una expresión, por lo que será ejecutada sin más. Es una forma elegante de ahorrarnos un <em>if</em> y aligerar (aunque sea de forma virtual) <a
title="Complejidad Ciclomática en Javascript. Concepto, ejemplos y herramientas de medición" href="http://www.etnassoft.com/2011/07/13/complejidad-ciclomatica-en-javascript-concepto-ejemplos-y-herramientas-de-medicion/">la complejidad ciclomática</a> del código.</p><p>Sin embargo, falta un paso más para que esto funcione: en caso de que el usuario haya utilizado la forma anterior de enviar su argumento asociado al método, tenemos que decirle a nuestro código que lo coja de ahí. También<strong> es necesario borrar el argumento cacheado tras su uso</strong> para que a la siguiente invocación del método, si no hemos asignado ningun elemento sobre el que actuar, no se utilice el que teníamos guardado de la vez anterior.</p><p>Por lo tanto, para llevar a cabo estas dos modificiaciones, necesitamos un par de líneas nuevas justo detrás de la que acabamos de explicar:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">core._args <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> core._args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
str <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
core._args <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span></pre></div></div><p>De nuevo se comprueba si <em>str</em> se corresponde con un valor nulo o indefinido en cuyo caso, lo reasignamos como cadena vacía.</p><p>La siguiente línea únicamente borra cualquier valor almacenado en el atributo <em>core._args</em> para que no sea reutilizado la proxima vez que se utilice la biblioteca.</p><p>Como mejora rápida, para aligerar un poco el código, las dos primeras líneas que hemos indicado pueden refactorizarse utilizando el mismo principio del <em>cortocircuito</em> anterior. Quedaría como sigue:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">str <span style="color: #339933;">=</span> core._args <span style="color: #339933;">||</span> str <span style="color: #339933;">||</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
core._args <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span></pre></div></div><p>Si lo unimos todo, nuestro código tiene ahora el siguiente aspecto:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #003366; font-weight: bold;">var</span> core <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">new</span> core.<span style="color: #660066;">fn</span>.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    core.<span style="color: #660066;">fn</span> <span style="color: #339933;">=</span> core.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      init<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> args <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        core._args <span style="color: #339933;">=</span> args<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> utils<span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Methods goes here</span>
    core.<span style="color: #660066;">trim</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      core._args <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> core._args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      str <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>str <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      core._args <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">return</span> str.<span style="color: #660066;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\s+|\s+$/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Return</span>
    <span style="color: #000066; font-weight: bold;">return</span> core<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  window.<span style="color: #660066;">utils</span> <span style="color: #339933;">=</span> window.$$ <span style="color: #339933;">=</span> utils<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Bien! Ahora toca probarlo para ver si funciona como se espera:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> sample1 <span style="color: #339933;">=</span> <span style="color: #3366CC;">'  Hello World  '</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> sample2 <span style="color: #339933;">=</span> <span style="color: #3366CC;">'   Good bye Lenin    '</span><span style="color: #339933;">;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'1'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample1 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Hello World'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'2'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Good bye Lenin'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'3'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample1 <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Hello World'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'4'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Good bye Lenin'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'5'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Good bye Lenin'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'6'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'7'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'8'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'9'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample1<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Hello World'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'10'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'11'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample1 <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Hello World'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'12'</span><span style="color: #339933;">,</span> $$.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'13'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample1 <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// 'Hello World'</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'14'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// ''</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'15'</span><span style="color: #339933;">,</span> $$<span style="color: #009900;">&#40;</span> sample1 <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span> sample2 <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//'Hello World'</span></pre></div></div><h2>Mejorando un poco el patrón</h2><p>Llegados a este punto, con nuestra estructura básica ya completa y con uno de sus posibles métodos ya implementados,<strong> podríamos decir que nuestro framework es funcional</strong>: los resultados son los esperados y el código resulta sencillo de extender y mantener. Sin embargo, como desarrolladores, podemos estar ya pensando en varias mejoras que complementen el trabajo realizado hasta ahora. Por ejemplo:</p><p>- Una fuerte comprobación de tipos en la entrada de argumentos.<br
/> - Un robusto sistema de manejo de excepciones para casos inesperados.<br
/> - Implementar un motor tipo <a
href="http://sizzlejs.com/">Sizzle</a> para ofrecer así soporte completo al API DOM.<br
/> - &#8230;</p><p>Aunque todo lo anterior podría resultar un buen ejercicio para comprobar si nos manejamos bien con esta estructura, quedaría pendiente una <em>feature</em> muchos más interesante: <strong>implementar un patrón de diseño encadenado</strong> que permita enlazar varios métodos sobre una misma referencia/entrada.</p><p>La finalidad de esta mejora sería conseguir una sintaxis similar a:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;">$$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'  Hello World  '</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">method2</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">method3</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// And so on...</span></pre></div></div><p>En una próxima entrega, veremos qué cambios tenemos que realizar en nuestro framework para conseguir este comportamiento, las ventajas que presenta y también sus inconvenientes en lo que a calidad de código se refiere. En relación a esto último, haremos alusión a la conocida <strong>Ley de Demeter</strong> y a cómo la enfrentan otras bibliotecas similares.</p><h2>Conclusión</h2><p>En este artículo hemos visto como, partiendo del patrón <em>tipo jQuery</em> que presentamos en otro artículo, podemos conseguir una arquitectura mejorada de gran flexibilidad a la hora de aplicar distintas funcionalidades sobre aquellos elementos en los que lo necesitemos.</p><p>Finalmente, hemos presentado una mejora importante (aún sin implementar) como es la que ofrece el patrón encadenado (<em>chaining pattern</em>) gracias a la cual, podremos aplicar varios métodos (funciones) sobre un mismo argumento en lo que resulta una sintaxis muy clara y legible.</p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=1784&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/09/28/estudiando-el-diseno-de-jquery-paso-a-paso-parte-2/feed/</wfw:commentRss> <slash:comments>21</slash:comments> </item> <item><title>Analizando el bucle for-in en Javascript</title><link>http://www.etnassoft.com/2011/09/21/analizando-el-bucle-for-in-en-javascript/</link> <comments>http://www.etnassoft.com/2011/09/21/analizando-el-bucle-for-in-en-javascript/#comments</comments> <pubDate>Wed, 21 Sep 2011 07:10:59 +0000</pubDate> <dc:creator>Carlos Benítez</dc:creator> <category><![CDATA[Javascript]]></category> <category><![CDATA[Sin categoría]]></category> <category><![CDATA[array]]></category> <category><![CDATA[bucles]]></category> <category><![CDATA[for-in]]></category> <category><![CDATA[rendimiento]]></category> <guid
isPermaLink="false">http://www.etnassoft.com/?p=1735</guid> <description><![CDATA[Introducción El estamento for-in es uno de esos pocos incomprendidos en Javascript. Su papel principal es el de recorrer un objeto pasando por cada una de sus propiedades para actuar sobre ellas de alguna manera; sin embargo, dado que en &#8230; <a
class="more-link" href="http://www.etnassoft.com/2011/09/21/analizando-el-bucle-for-in-en-javascript/">Seguir Leyendo...</a>]]></description> <content:encoded><![CDATA[<h2>Introducción</h2><p>El estamento <em>for-in</em> es uno de esos pocos incomprendidos en Javascript. Su papel principal es el de recorrer un objeto pasando por cada una de sus propiedades para actuar sobre ellas de alguna manera; sin embargo, dado que en Javascript los arrays son también objetos, podemos encontrarlo iterando por cada uno de los valores de estos últimos.</p><p>Se han escrito muchos artículos al respecto de este uso, sobre si es correcto o no, sobre el orden de enumeración obtenido, rendimiento, etc&#8230; Echemos un vistazo detenido a esta instrucción para ver cómo funciona con más detalle y corroborar o desmentir lo que sobre ella se dice.<br
/> <span
id="more-1735"></span></p><h2>Empecemos por lo básico</h2><p>La especificación <a
href="http://ecma262-5.com/ELS5_HTML.htm#Section_12.6.4">ECMAScript 262</a> define dos modos diferentes de declaración:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Method 1:</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> VariableDeclarationNoIn <span style="color: #000066; font-weight: bold;">in</span> Expression <span style="color: #009900;">&#41;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Method 2:</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span> LeftHandSideExpression  <span style="color: #000066; font-weight: bold;">in</span>  Expression  <span style="color: #009900;">&#41;</span></pre></div></div><p>Como vemos a simple vista, la única diferencia entre ambas fórmulas es el uso de <em>var</em> junto al primero de sus términos.</p><p>El método 1 es el más común y el que nos puede resultar más familiar. Declaramos una variable la cual recogerá a cada iteración el valor de los atributos que componen <strong>el objeto a recorrer</strong>. Destaco la palabra <em>objeto</em> porque con ella quiero englobar tanto al objeto considerado clásico (aquel de propiedades definidas mediante pares de nombre/valor), como a los <em>array</em> ya mencionados.</p><p>Un ejemplo sencillo sería el siguiente:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
  bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
  anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> property <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> property <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// foo</span>
<span style="color: #006600; font-style: italic;">// bar</span>
<span style="color: #006600; font-style: italic;">// anotherProperty</span></pre></div></div><p>Nótese que el valor devuelto se corresponde con el nombre de la propiedad; para acceder a su contenido, tendríamos que utilizar dicho nombre como índice del objeto:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
  foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
  bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
  anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> property <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myObj<span style="color: #009900;">&#91;</span>property<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// 1</span>
<span style="color: #006600; font-style: italic;">// 2</span>
<span style="color: #006600; font-style: italic;">// 3</span></pre></div></div><p>El segundo método, es más interesante. El término <em>LeftHandSideExpresion</em> hace referencia a cualquier tipo de expresión que pueda ser evaluada por el intérprete Javascript. Utilizando este patrón, asignamos en cada iteración el nombre de la propiedad a la expresión resultante del primer término.</p><p>La explicación puede parecer confusa, pero un ejemplo rápido nos muestra su funcionamiento:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
      bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
      anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;foo&quot;, &quot;bar&quot;, &quot;anotherProperty&quot;]</span></pre></div></div><p>De nuevo, observamos que obtenemos los nombres de las propiedades y no sus valores.</p><p><em>NOTA: Hay que tener cuidado con el punto y coma <em>;</em> que finaliza el <em>for-in</em>: al aceptar este estamento un bloque con instrucciones a ejecutar en cada iteración, si omitimos el punto y coma, el intérprete tomará la siguiente línea que encuentre como instrucción a ejecutar provocando comportamientos no deseados. Por ejemplo: </em></p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
      bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
      anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// I forgot the ';'!!</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// [&quot;foo&quot;]</span>
<span style="color: #006600; font-style: italic;">// [&quot;foo&quot;, &quot;bar&quot;]</span>
<span style="color: #006600; font-style: italic;">// [&quot;foo&quot;, &quot;bar&quot;, &quot;anotherProperty&quot;]</span></pre></div></div><p>El <em>console</em> se ha tomado como instrucción de bloque y será ejecutado a cada iteración por las propiedades del objeto.</p><p>Como hemos mencionado, con este método solo se toman los nombres de las propiedades por lo que si queremos acceder también al valor, al no contar con ese nombre almacenado, debemos utilizar el propio <em>array</em> que estamos montando para preguntar al objeto:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
      bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
      anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    myValues <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> lastItem <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
  myValues.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> myObj<span style="color: #009900;">&#91;</span> myArr<span style="color: #009900;">&#91;</span> lastItem <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myValues <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [ 1, 2, 3 ]</span></pre></div></div><p>No es un código muy elegante, pero parece ser la única forma de acceder al valor de una propiedad utilizando este tipo de estructura.</p><h2>¿Cuánto de flexible se vuelve esto?</h2><p>Podemos probar con formas más exóticas para ver qué ocurre.</p><p>Por ejemplo, la inicialización de varias variables (como haríamos por ejemplo en un <em>for</em> normal) produce en este caso un error inmediato:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      foo <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span>
      bar <span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
      anotherProperty <span style="color: #339933;">:</span> <span style="color: #CC0000;">3</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    myArr2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> myArr2<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// SyntaxError: invalid for/in left-hand side</span></pre></div></div><p>Sin embargo, si que podemos <em>alterar las expresiones</em> mediante un doble <em>in</em> en nuestra estructura:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
      foo <span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello World'</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    j <span style="color: #339933;">=</span> <span style="color: #3366CC;">'bar'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> myObj<span style="color: #339933;">,</span> j <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div><p>Esta compleja construcción en realidad no se corresponde con lo esperado: el segundo <em>in</em> actúa sobre la expresión evaluada en el primer término por lo que en realidad equivale a:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span> <span style="color: #003366; font-weight: bold;">var</span> j <span style="color: #339933;">=</span> foo <span style="color: #009900;">&#93;</span> <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #009900;">&#91;</span> bar <span style="color: #000066; font-weight: bold;">in</span> myObj <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span></pre></div></div><p>Esta estructura, como nos comentan en <a
href="http://twitter.com/kuvos">@kuvos</a>, tiene una consecuencia interesante en Javascript: eventualmente producirá un error, pero no en la fase de construcción sintáctica (es decir, no dará un error de sintaxis) sino en la de trazado del resultado. Esto hace a este estamento único dentro del lenguaje ya que es al parecer la única instrucción que requiere de un trazado <em>hacia atrás</em> una vez que el intérprete ha validado su sintaxis. Si esa expresión no resulta lógica, pese a ser correcta, producirá un error en tiempo de ejecución.</p><h2>¿Sobre qué propiedades itera?</h2><p>Pues según la especificación, esta instrucción itera por todas aquellas propiedades que poseen el valor interno [[Enumerable]] como verdadero. En la práctica, esto concierne a las propiedades definidas de facto en el objeto, a su prototipo, al prototipo del prototipo y así sucesivamente mientras nos remontamos en su cadena. Sin embargo, no se recogerían aquí las propiedades de los prototipos que hayan sido ocultadas por existir en dicha cadena prototípica un objeto anterior con una propiedad de igual nombre.</p><p>Para evitar todos estos elementos que en la mayoría de  ocasiones solo suponen ruido en los resultados, <a
title="A Survey of the JavaScript Programming Language" href="http://javascript.crockford.com/survey.html">Douglas Crockford</a> nos recomienda el uso del método <a
title="Object.prototype.hasOwnPropert" href="http://ecma262-5.com/ELS5_HTML.htm#Section_15.2.4.5"><em>hasOwnProperty</em></a> para filtrar todo aquello que provenga de herencia. Así tendríamos:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> arr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'b'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'c'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    indexesDefault <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    indexesClean <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
Array.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">each</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #006600; font-style: italic;">/*blah*/</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> index <span style="color: #000066; font-weight: bold;">in</span> arr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	indexesDefault.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> index <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>arr.<span style="color: #660066;">hasOwnProperty</span><span style="color: #009900;">&#40;</span>index<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		indexesClean.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> index <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> indexesDefault <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;each&quot;]</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> indexesClean <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// [&quot;0&quot;, &quot;1&quot;, &quot;2&quot;]</span></pre></div></div><p>Como vemos, con <em>hasOwnProperty</em> podemos suprimir de la ecuación aquellas propiedades/métodos legados mediante herencia.</p><h2>¿Y qué ocurre con los arrays?</h2><p>Como se ha dicho al principio, esta instrucción permite iterar por las propiedades de un objeto y en Javascript, un array es un objeto más:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">'foo'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'bar'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'hello'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">typeof</span> myArr <span style="color: #006600; font-style: italic;">// &quot;object&quot;</span></pre></div></div><p>Visto esto, podemos concluir pues que su uso es legítimo cuando se trata de recorrer los elementos que componen un array:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">'foo'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'bar'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'hello'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> element <span style="color: #000066; font-weight: bold;">in</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>element<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// foo</span>
<span style="color: #006600; font-style: italic;">// bar</span>
<span style="color: #006600; font-style: italic;">// hello</span></pre></div></div><p>Nótese que en la iteración, <em>element</em> guarda el índice del array en lugar del valor; es por ello que debemos acceder al mismo utilizando la estructura <em>myArr[element]</em>.</p><p>El resultado es el esperado. Sin embargo, debemos tener cuidado con una de las características de esta instrucción: <strong>el estándar no define el orden en que se recorrerá un objeto</strong>. De hecho, cuando recorremos un objeto tradicional, encontramos inconsistencias en un entorno multinavegador:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #CC0000;">3</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'b'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'foo'</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'c'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'d'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> result <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> prop <span style="color: #000066; font-weight: bold;">in</span> obj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    result.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>prop<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
result.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">//Chrome -&gt; &quot;1, 2, 3, foo&quot;</span>
<span style="color: #006600; font-style: italic;">//Other browsers -&gt; &quot;3, 2, foo, 1&quot;</span></pre></div></div><p>En el caso de un array, parece respetarse el orden de los índices en todas las plataformas testadas. Sin embargo, al no estar estandarizado este comportamiento, <strong>no deberíamos confiar en que siempre se devuelvan los valores en el orden esperado</strong>. Si dicho orden no resulta crítico para el flujo de nuestra aplicación, podemos entonces utlizar este método de forma segura.</p><h2>¿Y si hablamos de rendimiento?</h2><p>Visto el punto anterior, puede resultar interesante analizar qué resulta más óptimo cara al rendimiento de un script: recorrer un array con un bucle <em>for</em> tradicional o mediante esta variante del <em>for-in</em>&#8230; Pues midamos!</p><p>Para realizar las métricas, utlizaremos el servicio online <a
href="http://jsperf.com/for-vs-for-in-performance-with-strings">JSPerf</a> en el que se han montado los siguientes scripts:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Testing 'for' performance</span>
<span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">'En'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'un'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'lugar'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'de'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'la'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Mancha'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'de'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'cuyo'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'nombre'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'no'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'quiero'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'acordarme'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    myArrClone <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Preparo un array de pruebas</span>
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> i <span style="color: #339933;">=</span> myArr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;</span> i<span style="color: #339933;">;</span> x<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    myArrClone.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> myArr<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Y, para la variante <em>for-in</em>:</p><div
class="wp_syntax"><div
class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Testing 'for-in' performance</span>
<span style="color: #003366; font-weight: bold;">var</span> myArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> <span style="color: #3366CC;">'En'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'un'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'lugar'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'de'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'la'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Mancha'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'de'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'cuyo'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'nombre'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'no'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'quiero'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'acordarme'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    myArrClone <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">var</span> element <span style="color: #000066; font-weight: bold;">in</span> myArr <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  myArrClone.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> element <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>Los resultados son claros:</p><p><a
href="http://books.openlibra.com.s3.amazonaws.com/covers/2011/09/testing-for.png"><img
class="aligncenter size-full wp-image-1736" title="testing-for" src="http://books.openlibra.com.s3.amazonaws.com/covers/2011/09/testing-for.png" alt="" width="640" height="329" /></a></p><p><strong>Cuando hablamos de recorrer un array, el método <em>tradicional</em> resulta hasta un 400% más rápido.</strong></p><h2>Conclusión</h2><p>Tras revisar las métricas anteriores, queda de manifiesto que el uso del bucle <em>for-in</em> debería limitarse únicamente a recorrer un objeto tradicional (aquel que implementa pares de nombre/valor) y nunca un array. Esta afirmación responde a una cuestión de rendimiento patente en las estadísticas.</p><p>Una vez asumido el punto anterior, conviene saber que existen dos formas de construir este estamento: una básica en la que definimos una variable y a la que se asigna el nombre de la propiedad correspondiente en cada iteración y, una segunda en la que dicho nombre se asocia al resultado de evaluar una expresión. Con respecto a esta última estructura, descubrimos que podemos obtener errores inesperados debido a que el intérprete puede encontrarse con expresiones sin sentido (aún correctas sintácticamente) dentro de la lógica de la instrucción.</p><p>No podemos garantizar en ningún caso el orden en que se recorreran las propiedades de nuestro objeto por lo que, en caso de que dicho orden resulte crítico para nuestra aplicación, debemos buscar alguna forma alternativa de almacenamiento como, por ejemplo, un array tradicional.</p><h2>Para saber más</h2><p>Angus Croll, <a
href="http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/">Exploring JavaScript for-in loops</a><br
/> Peter van der Zee, <a
href="http://qfox.nl/weblog/238">for-in grammar</a><br
/> ECMA262, <a
href="http://ecma262-5.com/ELS5_HTML.htm#Section_12.6.4">The for-in Statement</a></p> <img
src="http://www.etnassoft.com/?ak_action=api_record_view&id=1735&type=feed" alt="" />]]></content:encoded> <wfw:commentRss>http://www.etnassoft.com/2011/09/21/analizando-el-bucle-for-in-en-javascript/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> </channel> </rss>
<!-- Dynamic page generated in 5.870 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-23 06:20:53 -->
<!-- Compression = gzip -->
