<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Fernando Barrios]]></title><description><![CDATA[Un blog con tutoriales sobre JavaScript, React, CSS y otros temas relacionados con el desarrollo de software.]]></description><link>https://jfbarrios.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 07:43:52 GMT</lastBuildDate><atom:link href="https://jfbarrios.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Cómo creé mi propio “Kindle Whispersync” para aprender idiomas: lectura + audio sincronizados]]></title><description><![CDATA[Siempre he sentido que leer y escuchar al mismo tiempo es una de las formas más efectivas de aprender un idioma. La idea de Amazon Whispersync me parecía perfecta: compras el libro en Kindle, el audiolibro en Audible y tienes sincronización. El probl...]]></description><link>https://jfbarrios.com/como-cree-mi-propio-kindle-whispersync-para-aprender-idiomas-lectura-audio-sincronizados</link><guid isPermaLink="true">https://jfbarrios.com/como-cree-mi-propio-kindle-whispersync-para-aprender-idiomas-lectura-audio-sincronizados</guid><category><![CDATA[whispersync]]></category><category><![CDATA[kindle]]></category><category><![CDATA[ #LanguageSkills]]></category><category><![CDATA[learning]]></category><category><![CDATA[english-lesson]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Mon, 15 Sep 2025 14:28:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/vcF5y2Edm6A/upload/a116d3b0474a203b3829677e0295978c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Siempre he sentido que leer y escuchar al mismo tiempo es una de las formas más efectivas de aprender un idioma. La idea de Amazon Whispersync me parecía perfecta: compras el libro en Kindle, el audiolibro en Audible y tienes sincronización. El problema fue que yo necesitaba materiales adecuados para mi nivel y, además, el libro específico que quería no tenía la opción de Whispersync. Decidí entonces construir mi propia versión casera, usando recursos gratuitos y de dominio público. Aquí te cuento, paso a paso y tal como lo fui haciendo.</p>
<p>Si quieres ver un ejemplo funcionando, puedes abrir mi visor web aquí: <a target="_blank" href="https://jfernandogt.github.io/gentler-viewer/">https://jfernandogt.github.io/gentler-viewer/</a></p>
<p>Lo primero fue resolver el tema del nivel. No quería lanzarme a una novela compleja y frustrarme a las diez páginas. Recordé <a target="_blank" href="https://www.penguinreaders.co.uk/">Penguin Readers</a>, que clasifica libros por niveles de inglés. Entré a su sitio, revisé los niveles (A1–C1) y me armé una lista de obras que me interesaban y que, idealmente, existieran en dominio público. Aquí fue donde hice mi “curaduría”: una selección cuidadosa de historias que me motivaran y encajaran con mi nivel. Al final elegí The Hound of the Baskervilles, de Arthur Conan Doyle.</p>
<p>Con la decisión tomada, me fui a por el texto. En Project Gutenberg encontré la obra y descargué la versión en TXT: <a target="_blank" href="https://www.gutenberg.org/ebooks/2852">https://www.gutenberg.org/ebooks/2852</a>. Abrí el archivo y le hice una limpieza rápida. Quitar los encabezados y pies de página que añade Gutenberg. Esta parte es clave: si el texto no coincide con lo que dice el narrador, la alineación se desajusta.</p>
<p>El siguiente paso fue conseguir el audio. En LibriVox encontré el audiolibro: <a target="_blank" href="https://librivox.org/the-hound-of-the-baskervilles-by-arthur-conan-doyle/">https://librivox.org/the-hound-of-the-baskervilles-by-arthur-conan-doyle/</a></p>
<p>Escuché los primeros minutos y los comparé con el texto de Gutenberg. La coincidencia era buena: mismo orden de capítulos, lenguaje muy similar y una narración clara. Eso me dio confianza para seguir. Descargué los capítulos en MP3.</p>
<p>Con texto y audio listos, pasé a la parte técnica: la alineación. Usé <a target="_blank" href="https://github.com/strob/gentle/">Gentle</a>, una herramienta de forced alignment que toma un archivo de audio y el texto correspondiente y devuelve un JSON con marcas de tiempo por palabra. Seguí las instrucciones del repositorio para correrlo localmente y, por prudencia, empecé únicamente con el capítulo 1.</p>
<p>Una vez tuve el JSON de Gentle, me puse a construir el visor. Quería algo simple y accesible desde cualquier dispositivo: una página web con HTML, CSS y JavaScript. El visor carga el audio desde una URL pública (por ejemplo, un MP3 alojado en GitHub Pages) y, en paralelo, carga el JSON con la alineación. Con eso, el script puede resaltar en tiempo real la palabra que se está pronunciando mientras el audio avanza. Agregué dos detalles que cambiaron por completo la experiencia: la posibilidad de hacer clic en una parte del texto para saltar a ese punto del audio, así, si una frase se me hacía complicada, podía repetirla de inmediato sin perder el ritmo.</p>
<p>Para alojarlo, opté por GitHub Pages. Subí el HTML, el CSS, el JavaScript y probé con un capítulo de The Hound of the Baskervilles. Ajusté cosas de usabilidad sobre la marcha: un control de velocidad, un modo oscuro para leer de noche. Cuando estuve conforme, dejé el visor accesible públicamente para poder usarlo desde el teléfono, la computadora o la tablet sin instalar nada. Puedes verlo en acción aquí: <a target="_blank" href="https://jfernandogt.github.io/gentler-viewer/">https://jfernandogt.github.io/gentler-viewer/</a></p>
<p>Lo más valioso del proceso es cómo impacta en el aprendizaje del idioma. Tener texto y audio sincronizados me ayudó a fijar la relación entre lo que veo y lo que escucho, además que al empezar con una obra que se ajustaba a mi nivel, la experiencia fue desafiante pero llevadera, sin caer en la frustración.</p>
<p>Te dejo algunas capturas de pantalla</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757946321665/44a1dc14-c148-4504-8d4c-673e85fce060.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757946389816/2eda26c0-196d-4818-a45d-e3d85ed1e246.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Usar Docker y Docker Compose sin instalar Docker Desktop en Mac]]></title><description><![CDATA[Preámbulo
Con los recientes cambios en las licencias de Docker Desktop, muchos desarrolladores y empresas han comenzado a buscar alternativas para manejar contenedores sin incurrir en costos adicionales o restricciones de licencia. Aunque herramienta...]]></description><link>https://jfbarrios.com/usar-docker-y-docker-compose-sin-instalar-docker-desktop-en-mac</link><guid isPermaLink="true">https://jfbarrios.com/usar-docker-y-docker-compose-sin-instalar-docker-desktop-en-mac</guid><category><![CDATA[alternativas]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Docker compose]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Fri, 18 Oct 2024 05:00:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hGV2TfOh0ns/upload/1477529c91b990b5fb99e4051c261af4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-preambulo">Preámbulo</h2>
<p>Con los recientes cambios en las <a target="_blank" href="https://www.docker.com/blog/updating-product-subscriptions/">licencias de Docker Desktop</a>, muchos desarrolladores y empresas han comenzado a buscar alternativas para manejar contenedores sin incurrir en costos adicionales o restricciones de licencia. Aunque herramientas como Podman o Rancher ofrecen soluciones robustas, a menudo presentan una curva de aprendizaje más pronunciada para quienes están acostumbrados a Docker, o bien requieren de muchas configuraciones para que logren funcionar de la misma manera en la que Docker lo hace. Afortunadamente, es posible utilizar Docker sin depender de Docker Desktop. En este artículo, exploraremos cómo hacerlo de manera efectiva.</p>
<p>Decidí escribir este artículo tras haber pasado seis meses probando Podman y Rancher. Aunque ambas herramientas son poderosas, encontré que trabajar con Docker sin Docker Desktop ofrecía una experiencia más directa para mis necesidades. Sin embargo, me encontré con ciertas limitaciones que quiero abordar a lo largo del artículo.</p>
<p>Si quieres una script que haga todo automáticamente, puedes ir a mi repositorio: <a target="_blank" href="https://github.com/jfernandogt/install-docker-without-docker-desktop-mac/tree/main">https://github.com/jfernandogt/install-docker-without-docker-desktop-mac/tree/main</a></p>
<h2 id="heading-instalacion">Instalación</h2>
<p>El único requisito previo es Homebrew, que si no lo tienes instalado, puedes encontrar instrucciones en su página <a target="_blank" href="https://brew.sh/">aquí</a>.</p>
<p>Para empezar, debemos de instalar Docker y el asistente de gestión de credenciales. Este asistente nos permitirá usar el llavero de macOS como almacén de credenciales para repositorios de contenedores remotos en lugar de Docker Desktop.</p>
<pre><code class="lang-bash">brew install docker docker-credential-helper docker-compose docker-Buildx
</code></pre>
<p>En algún momento nos podremos llegar a topar con este error: <code>'docker-credential-desktop not installed'</code> para esto, debemos actualizar las configuraciones de docker. Lo primero que haremos es validar que exista el directorio de <code>.docker</code> y si no, crearlo con el comando siguiente:</p>
<pre><code class="lang-bash">mkdir ~/.docker
</code></pre>
<p>Ahora editamos el archivo con nano</p>
<pre><code class="lang-bash">nano ~/.docker/config.json
</code></pre>
<p>Las claves importantes que debemos actualizar son <code>credsStore</code> y <code>currentContext</code></p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"auths"</span>: {},
    <span class="hljs-attr">"credsStore"</span>: <span class="hljs-string">"osxkeychain"</span>,
    <span class="hljs-attr">"currentContext"</span>: <span class="hljs-string">"colima"</span>
}
</code></pre>
<p>El siguiente paso es configurar <code>docker-compose</code> como un complemento de Docker para poder usar docker compose como comando en lugar del script <code>docker-compose</code> heredado. Primero, crearemos una carpeta en el directorio de inicio para almacenar los complementos de Docker CLI:</p>
<pre><code class="lang-bash">mkdir -p ~/.docker/cli-plugins
</code></pre>
<p>Luego, crearemos un enlace simbólico con el comando docker-compose en esa nueva carpeta:</p>
<pre><code class="lang-bash">ln -sfn $(brew --prefix)/opt/docker-compose/bin/docker-compose ~/.docker/cli-plugins/docker-compose
</code></pre>
<p>Ahora podemos comprobar si el comando de docker compose está funcionando:</p>
<pre><code class="lang-bash">docker compose
</code></pre>
<p>Debería devolvernos algo parecido a lo siguiente:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732642180025/81cd6677-11c1-4769-9a1a-8cb91b4b55b9.png" alt class="image--center mx-auto" /></p>
<p>También necesitaremos Buildx para crear algunos contenedores Docker. Este se instala con Docker Engine en macOS, pero en nuestro caso lo instalamos en el paso 1 con homebrew. Lo único que debemos hacer es crear un enlace simbólico:</p>
<pre><code class="lang-bash">ln -sfn $(brew --prefix)/opt/docker-buildx/bin/docker-buildx ~/.docker/cli-plugins/docker-buildx
</code></pre>
<p>Ahora debemos instalar un container runtime, en mi caso opté por Colima</p>
<pre><code class="lang-bash">brew install colima
</code></pre>
<p>Por último para levantar o detener el servicio, bastará con ejecutar sus respectivos comandos</p>
<pre><code class="lang-bash">colima start <span class="hljs-comment"># Para iniciar el servicio</span>
colima stop <span class="hljs-comment"># Para detener el servicio</span>
</code></pre>
<p>Para todos aquellos que les gustan las interfaces gráficas, pueden usar la extensión de <a target="_blank" href="https://code.visualstudio.com/docs/containers/overview">Docker para VS Code</a>, la cual lee el <code>currentContext</code> de la configuración que actualizamos y automáticamente se conecta y nos muestra la misma información que teníamos en el Docker Desktop.</p>
<p>Una segunda alternativa si no quisiéramos usar la extensión de VS Code y tenemos <a target="_blank" href="https://raycast.com/?via=fernando">Raycast</a> instalado, podremos usar su <a target="_blank" href="https://www.raycast.com/priithaamer/docker">extensión de Docker</a>.</p>
<h2 id="heading-configuracion-del-socket">Configuración del socket</h2>
<p>Algunas aplicaciones se conectan directamente al socket de Docker, el cual usualmente se encuentra en <code>/var/run/docker.sock</code> , para estas aplicaciones lo mejor es crear un enlace simbólico de colima hacia esa ruta, ejecutando este comando:</p>
<pre><code class="lang-bash">sudo ln -s /Users/TU_USUARIO/.colima/default/docker.sock /var/run/docker.sock
</code></pre>
<h2 id="heading-conclusiones">Conclusiones</h2>
<p>Con estas instrucciones, puedes seguir utilizando Docker sin la necesidad de Docker Desktop, manteniendo así la flexibilidad de tus proyectos y asegurando el cumplimiento de las nuevas políticas de licencias. Al final si lo que buscamos es tener la experiencia más cercana a Docker, no hay nada más cercano a eso que usar el mismo CLI de Docker.</p>
]]></content:encoded></item><item><title><![CDATA[Top 10 de certificaciones que todo Developer debería de considerar]]></title><description><![CDATA[El año pasado, me enfrenté al desafío de obtener la certificación "Certified Kubernetes Developer CKAD". En mi equipo de trabajo, la demanda de conocimientos en Kubernetes estaba en aumento, y aunque nunca antes había trabajado con esta tecnología, m...]]></description><link>https://jfbarrios.com/top-10-de-certificaciones-que-todo-developer-deberia-de-considerar</link><guid isPermaLink="true">https://jfbarrios.com/top-10-de-certificaciones-que-todo-developer-deberia-de-considerar</guid><category><![CDATA[Certification]]></category><category><![CDATA[courses]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Fri, 09 Feb 2024 03:25:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/oqStl2L5oxI/upload/503a8b7941c936cea4ecbbd30bf9f3ae.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>El año pasado, me enfrenté al desafío de obtener la certificación "Certified Kubernetes Developer CKAD". En mi equipo de trabajo, la demanda de conocimientos en Kubernetes estaba en aumento, y aunque nunca antes había trabajado con esta tecnología, me lancé a la aventura. Hasta ese momento, mi experiencia más compleja se limitaba a dockerizar aplicaciones.</p>
<p>Opté por tomar esta certificación como una oportunidad para sumergirme profundamente en el mundo de Kubernetes. Después de 4 meses de intenso trabajo, completando cursos, realizando simulaciones y sacrificando horas de sueño (lo que generó algunos regaños de mi esposa), ¡logré obtener la certificación en mi primer intento!</p>
<p>Esta entrada en el blog pretende compartir mi experiencia y reflexionar sobre las certificaciones que considero valiosas para los desarrolladores de software. Si bien algunas pueden no ser relevantes para todos los perfiles, estas son las que, en mi opinión, pueden agregar un gran valor a nuestra carrera profesional.</p>
<p>Es importante destacar que las certificaciones no son un indicador absoluto de los conocimientos de una persona, pero desde mi experiencia, han aportado numerosos beneficios:</p>
<ol>
<li><p><strong>Validación de conocimientos</strong>: Las certificaciones sirven como un respaldo tangible de que poseo un cierto nivel de conocimientos en la materia. Es una forma de demostrar mis habilidades y competencias en un área específica.</p>
</li>
<li><p><strong>Claridad para no expertos</strong>: Para aquellos que no están familiarizados con el mundo de la tecnología, las certificaciones proporcionan una comprensión clara de mi experiencia y habilidades como desarrollador. Facilitan la comunicación sobre mi formación y trayectoria profesional.</p>
</li>
<li><p><strong>Diferenciación en el mercado laboral</strong>: Tener certificaciones destacadas en mi currículum puede hacer que resalte entre otros candidatos en el mercado laboral. Demuestra un compromiso con el aprendizaje continuo y la mejora profesional.</p>
</li>
<li><p><strong>Profundización en temas específicos</strong>: A través de la preparación para las certificaciones, he tenido la oportunidad de profundizar en temas específicos que de otro modo podrían haber quedado fuera de mi radar. Esto me ha permitido adquirir un entendimiento más completo y detallado de ciertos aspectos de la tecnología.</p>
</li>
<li><p><strong>Acceso a nuevos conocimientos</strong>: Las certificaciones también han abierto puertas a áreas de conocimiento a las que, por mi carrera profesional, no habría estado expuesto de otra manera. Me han permitido explorar nuevos temas y expandir mi conjunto de habilidades de manera significativa.</p>
</li>
</ol>
<h3 id="heading-10-certificaciones-que-considero-que-todo-desarrollador-deberia-de-considerar">10 certificaciones que considero que todo desarrollador debería de considerar</h3>
<p><strong>Cloud</strong></p>
<ol>
<li><p><strong>Certificación AWS Certified Developer - Associate</strong>: Esta certificación valida las habilidades en el desarrollo de aplicaciones en la nube utilizando servicios de Amazon Web Services (AWS).</p>
</li>
<li><p><strong>Certificación Microsoft Certified: Azure Developer Associate</strong>: Similar a la certificación de AWS, pero enfocada en el desarrollo de aplicaciones en la nube utilizando la plataforma de Microsoft Azure.</p>
</li>
<li><p><strong>Certificación Google: Professional Cloud Developer</strong>: Similar a la certificación de AWS o Azure, pero enfocada en el desarrollo de aplicaciones en la nube utilizando la plataforma de Google Developer Cloud.</p>
</li>
<li><p><strong>CKAD (Certified Kubernetes Application Developer)</strong>: Esta certificación valida las habilidades en el desarrollo de aplicaciones en contenedores utilizando Kubernetes, un componente fundamental en entornos de nube y despliegue de aplicaciones modernas.</p>
</li>
</ol>
<p><strong>Desarrollo</strong></p>
<ol>
<li><p><strong>JSNAD (JavaScript Developer - Professional Certification)</strong>: Esta certificación se centra en validar habilidades avanzadas en JavaScript, abarcando tanto frontend como backend y cubriendo conceptos esenciales para el desarrollo de aplicaciones web modernas.</p>
</li>
<li><p><strong>JSNSD (JavaScript Developer - Professional Certification)</strong>: Similar a JSNAD, pero enfocada específicamente en el desarrollo frontend, esta certificación valida habilidades en HTML, CSS, JavaScript y frameworks frontend populares.</p>
</li>
</ol>
<p><strong>Gestión de proyectos</strong></p>
<ol>
<li><p><strong>CSM (Certified ScrumMaster)</strong>: Esta certificación valida las habilidades en Scrum y la capacidad para servir como líder de equipo en un entorno ágil. Es una certificación fundamental para aquellos que desean trabajar en equipos Scrum y liderar iniciativas ágiles.</p>
</li>
<li><p><strong>CSD (Certified Scrum Developer) y A-CSD</strong>: La certificación CSD valida las habilidades técnicas de un desarrollador en un entorno Scrum. Se centra en prácticas de desarrollo ágil, colaboración efectiva en equipo y entrega continua de software de alta calidad dentro de un marco de trabajo Scrum. Respecto a la de A-CSD, esta certificación es una extensión del CSD y valida habilidades técnicas adicionales y más avanzadas en el contexto de Scrum. Se centra en técnicas de desarrollo avanzadas, diseño de software sólido, refactorización y entrega de software de alta calidad en equipos Scrum.</p>
</li>
<li><p><strong>Team Kanban Practitioner (TKP):</strong> valida la comprensión y aplicación práctica de los principios y prácticas de Kanban en equipos de trabajo. Esta certificación se centra en cómo visualizar el trabajo, limitar el trabajo en curso (WIP), gestionar el flujo de trabajo y mejorar continuamente el proceso de entrega</p>
</li>
</ol>
<p><strong>Control de calidad</strong></p>
<ol>
<li><strong>Certified Tester Foundation Level (CTFL)</strong>: Esta certificación es fundamental en el campo de la prueba de software, cubriendo conceptos básicos de pruebas, técnicas de diseño de pruebas y gestión de pruebas, lo cual es esencial para garantizar la calidad de las aplicaciones web.</li>
</ol>
<p>Como habrás notado, no he dejado ninguna que esté relacionada a la seguridad, cuento con poca información en ese tema, por lo que acepto sugerencias :)</p>
]]></content:encoded></item><item><title><![CDATA[Comprendiendo "Syntactic Sugar" - Una guía simple]]></title><description><![CDATA[TLDR
Comprendiendo "Syntactic Sugar" es una guía simple que explica cómo ciertas características en JavaScript, como funciones de flecha y operadores de propagación, hacen que el código sea más legible y conciso sin agregar nuevas funcionalidades. Es...]]></description><link>https://jfbarrios.com/comprendiendo-syntactic-sugar-una-guia-simple</link><guid isPermaLink="true">https://jfbarrios.com/comprendiendo-syntactic-sugar-una-guia-simple</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[syntactic sugar]]></category><category><![CDATA[software development]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Wed, 07 Jun 2023 18:24:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/SGI0i5sHCL8/upload/a724979f2a36d412b8854520be2b0c6c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-tldr">TLDR</h2>
<p>Comprendiendo "Syntactic Sugar" es una guía simple que explica cómo ciertas características en JavaScript, como funciones de flecha y operadores de propagación, hacen que el código sea más legible y conciso sin agregar nuevas funcionalidades. Estas características mejoran la legibilidad y expresividad del código, lo que facilita el desarrollo.</p>
<h2 id="heading-introduccion-al-syntactic-sugar">Introducción al "Syntactic Sugar"</h2>
<p>El "syntactic sugar" en JavaScript es como un dulce que hace que nuestro código sea más fácil de leer y entender. 🍬✨</p>
<p>Cuando hablamos de syntactic sugar, nos referimos a características del lenguaje que no añaden nuevas funcionalidades, pero nos permiten escribir código de una manera más sencilla y concisa. Es como si le pusieran un poco de azúcar al lenguaje para hacerlo más agradable y legible. 🎉</p>
<h2 id="heading-proposito-y-beneficios">Propósito y beneficios</h2>
<p>El propósito principal de este azúcar sintáctico es mejorar la legibilidad y la expresividad del código. Al utilizar una sintaxis más clara y concisa, nuestro código se vuelve más fácil de entender, lo que resulta en un desarrollo más eficiente y rápido. ⚡️💻</p>
<p>Algunos ejemplos de syntactic sugar en JavaScript son las funciones de flecha (<code>=&gt;</code>), el operador de propagación (<code>...</code>), el operador de desestructuración y muchos otros. Estas características nos permiten escribir código de forma más breve y elegante. 😍💻</p>
<h2 id="heading-ejemplos-comunes">Ejemplos comunes</h2>
<pre><code class="lang-javascript"><span class="hljs-comment">// 1. Arrow functions</span>
<span class="hljs-keyword">const</span> add = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;

<span class="hljs-comment">// 2. Template literals</span>
<span class="hljs-keyword">const</span> greeting = <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;

<span class="hljs-comment">// 3. Object property shorthand</span>
<span class="hljs-keyword">const</span> x = <span class="hljs-number">10</span>, y = <span class="hljs-number">20</span>;
<span class="hljs-keyword">const</span> point = { x, y };

<span class="hljs-comment">// 4. Destructuring assignment</span>
<span class="hljs-keyword">const</span> { firstName, lastName } = person;

<span class="hljs-comment">// 5. Default parameters</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">a, b = <span class="hljs-number">1</span></span>) </span>{
  <span class="hljs-keyword">return</span> a * b;
}

<span class="hljs-comment">// 6. Spread syntax</span>
<span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> arr2 = [...arr1, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>];

<span class="hljs-comment">// 7. Rest parameters</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">...numbers</span>) </span>{
  <span class="hljs-keyword">return</span> numbers.reduce(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b, <span class="hljs-number">0</span>);
}
</code></pre>
<p>¿No es genial? 😄✨</p>
<h2 id="heading-conclusiones">Conclusiones</h2>
<p>Recuerda utilizar el syntactic sugar con moderación y mantener la consistencia en tu código para evitar confusiones. Además, documentar y comentar tu código siempre es una buena práctica para que otros desarrolladores puedan entenderlo fácilmente. 📝💡</p>
<p>¡Ah, y no te olvides de mantener tu conocimiento actualizado sobre las novedades de JavaScript! Siempre hay nuevas formas de endulzar nuestro código. 🍭🚀</p>
<p>¡Feliz programación! 💻💖</p>
]]></content:encoded></item><item><title><![CDATA[Patrón de diseño Higher-Order Component (HOC) en React y JavaScript]]></title><description><![CDATA[Introducción
El patrón de diseño Higher-Order Component (HOC) es un patrón avanzado en React que se utiliza para reutilizar la lógica de los componentes. Un HOC es una función que toma un componente y devuelve otro componente con funcionalidades adic...]]></description><link>https://jfbarrios.com/patron-de-diseno-higher-order-component-hoc-en-react-y-javascript</link><guid isPermaLink="true">https://jfbarrios.com/patron-de-diseno-higher-order-component-hoc-en-react-y-javascript</guid><category><![CDATA[React]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Thu, 16 Mar 2023 16:55:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UYsBCu9RP3Y/upload/927005f48cc77ee32aff5915666f2efa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduccion">Introducción</h2>
<p>El patrón de diseño Higher-Order Component (HOC) es un patrón avanzado en React que se utiliza para reutilizar la lógica de los componentes. Un HOC es una función que toma un componente y devuelve otro componente con funcionalidades adicionales o modificadas. En este artículo, exploraremos el patrón de diseño HOC con ejemplos en React y JavaScript.</p>
<h2 id="heading-hoc-en-detalle">HOC en detalle</h2>
<p>La idea detrás de este patrón es aprovechar la composición en lugar de la herencia para extender la funcionalidad de los componentes de React. Entonces con la ayuda de la composición podemos tomar un componente, añadirle funcionalides y luego devolver el componente.</p>
<h2 id="heading-ejemplo-basico-de-hoc-en-javascript">Ejemplo básico de HOC en JavaScript</h2>
<p>Antes de adentrarnos en React, veamos un ejemplo básico de HOC en JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withLogging</span>(<span class="hljs-params">fn</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Llamando a la función: <span class="hljs-subst">${fn.name}</span>`</span>, args);
    <span class="hljs-keyword">const</span> result = fn(...args);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Resultado: <span class="hljs-subst">${result}</span>`</span>);
    <span class="hljs-keyword">return</span> result;
  };
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">suma</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-keyword">const</span> sumaConLogging = withLogging(suma);
<span class="hljs-keyword">const</span> resultado = sumaConLogging(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>); <span class="hljs-comment">// Llamando a la función: suma [3, 4]</span>
                                        <span class="hljs-comment">// Resultado: 7</span>
</code></pre>
<p>En este ejemplo, <code>withLogging</code> es un HOC que toma una función <code>fn</code> y devuelve una nueva función que registra el nombre de la función, sus argumentos y su resultado antes de llamarla.</p>
<h2 id="heading-ejemplo-de-hoc-en-react">Ejemplo de HOC en React</h2>
<p>Ahora, veamos un ejemplo de HOC en React. Supongamos que tenemos dos componentes funcionales: <code>ComponenteA</code> y <code>ComponenteB</code>. Queremos agregar la funcionalidad de contar el número de veces que se hace clic en un botón en ambos componentes. En lugar de agregar la lógica de conteo en cada componente individualmente, podemos crear un HOC que envuelva ambos componentes y les proporcione la funcionalidad de conteo.</p>
<p>Aquí está el código:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-comment">// HOC que agrega la funcionalidad de conteo</span>
<span class="hljs-keyword">const</span> withCounter = <span class="hljs-function">(<span class="hljs-params">WrappedComponent</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> WithCounter = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

    <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
      setCount(count + <span class="hljs-number">1</span>);
    };

    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">WrappedComponent</span> <span class="hljs-attr">handleClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">count</span>=<span class="hljs-string">{count}</span> /&gt;</span></span>;
  };

  <span class="hljs-keyword">return</span> WithCounter;
};

<span class="hljs-comment">// ComponenteA sin la funcionalidad de conteo</span>
<span class="hljs-keyword">const</span> ComponenteA = <span class="hljs-function">(<span class="hljs-params">{ handleClick }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Componente A<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
};

<span class="hljs-comment">// ComponenteB sin la funcionalidad de conteo</span>
<span class="hljs-keyword">const</span> ComponenteB = <span class="hljs-function">(<span class="hljs-params">{ handleClick }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Componente B<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
};

<span class="hljs-comment">// Envolver ComponenteA y ComponenteB con el HOC</span>
<span class="hljs-keyword">const</span> ComponenteAConConteo = withCounter(ComponenteA);
<span class="hljs-keyword">const</span> ComponenteBConConteo = withCounter(ComponenteB);

<span class="hljs-comment">// Renderizar ComponenteA y ComponenteB con la funcionalidad de conteo agregada</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponenteAConConteo</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponenteBConConteo</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>En este ejemplo, creamos un HOC llamado <code>withCounter</code> que acepta un componente como argumento y devuelve un nuevo componente llamado <code>WithCounter</code>. <code>WithCounter</code> tiene su propio estado para contar el número de clics y una función <code>handleClick</code> que actualiza el estado cada vez que se hace clic en el botón.</p>
<p>Luego, envolvemos los componentes <code>ComponenteA</code> y <code>ComponenteB</code> con el HOC <code>withCounter</code> para agregarles la funcionalidad de conteo. Finalmente, renderizamos los componentes envueltos <code>ComponenteAConConteo</code> y <code>ComponenteBConConteo</code> en nuestra aplicación principal.</p>
<p>De esta manera, logramos reutilizar la funcionalidad de conteo en múltiples componentes y mantener nuestro código más limpio y modular.</p>
]]></content:encoded></item><item><title><![CDATA[Scrum vs Kanban: Mi opinión como dev después de más de 8 años de trabajo.]]></title><description><![CDATA[Antes de adentrarnos en las principales diferencias, es conveniente platicar un poco sobre cada una.
Scrum
Scrum es un marco ágil para gestionar y completar proyectos complejos. Originalmente se desarrolló para el desarrollo de software, pero ahora s...]]></description><link>https://jfbarrios.com/scrum-vs-kanban-mi-opinion-como-dev-despues-de-mas-de-8-anos-de-trabajo</link><guid isPermaLink="true">https://jfbarrios.com/scrum-vs-kanban-mi-opinion-como-dev-despues-de-mas-de-8-anos-de-trabajo</guid><category><![CDATA[Scrum]]></category><category><![CDATA[kanban]]></category><category><![CDATA[agile]]></category><category><![CDATA[teamwork]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Thu, 09 Feb 2023 14:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OXmym9cuaEY/upload/f56aa6eebba9621a754d783b5d4adfd6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Antes de adentrarnos en las principales diferencias, es conveniente platicar un poco sobre cada una.</p>
<h2 id="heading-scrum">Scrum</h2>
<p>Scrum es un marco ágil para gestionar y completar proyectos complejos. Originalmente se desarrolló para el desarrollo de software, pero ahora se usa ampliamente en una variedad de industrias, que incluyen marketing, finanzas y atención médica.</p>
<p>Scrum se basa en los principios de transparencia, inspección y adaptación. Proporciona un proceso estructurado y repetible para entregar el trabajo, con roles, eventos y artefactos definidos.</p>
<p>Scrum enfatiza la entrega de un incremento de producto entregable al final de cada sprint, para que el equipo esté continuamente entregando valor al cliente. También fomenta la mejora continua, con retrospectivas periódicas y la capacidad de ajustar el objetivo del sprint a mitad del sprint, si es necesario.</p>
<p>Scrum es ideal para proyectos complejos que requieren una estrecha colaboración, equipos multifuncionales y comentarios regulares de los clientes y las partes interesadas.</p>
<h2 id="heading-kanban">Kanban</h2>
<p>Kanban es un sistema visual para administrar y optimizar flujos de trabajo, desarrollado originalmente en la industria manufacturera. Ahora se usa ampliamente en el desarrollo de software y otros campos para ayudar a los equipos a entregar elementos de trabajo de manera más efectiva y eficiente.</p>
<p>En Kanban, los elementos de trabajo se representan como tarjetas en un tablero visual y cada tarjeta se mueve de izquierda a derecha a través de una serie de columnas, que representan diferentes etapas del flujo de trabajo. Los equipos usan límites WIP (trabajo en curso) para administrar el flujo y garantizar que los elementos de trabajo se completen de la manera más rápida y eficiente posible.</p>
<p>Kanban enfatiza la mejora continua y alienta a los equipos a realizar cambios en el proceso según sea necesario. No tiene time boxes, sprints o roles definidos, lo que lo convierte en un enfoque más flexible que se puede adaptar a las necesidades de diferentes equipos y proyectos.</p>
<h2 id="heading-principales-diferencias">Principales diferencias</h2>
<p>Estas son las diferencias clave entre las metodologías Scrum y Kanban:</p>
<ol>
<li><p>Proceso: Scrum es un proceso estructurado e iterativo con roles, ceremonias y cuadros de tiempo definidos. Kanban es un enfoque más flexible basado en el flujo sin cuadros de tiempo ni roles definidos.</p>
</li>
<li><p>Elementos de trabajo: Scrum utiliza "backlogs" tanto para producto como para el sprint para administrar los elementos de trabajo, mientras que Kanban utiliza un tablero visual para realizar un seguimiento de los elementos de trabajo a través de diferentes etapas del proceso.</p>
</li>
<li><p>Tiempo de entrega <em>(Lead time)</em>: Scrum se enfoca en entregar un incremento completo del producto al final de cada sprint, mientras que Kanban se enfoca en brindar pequeñas mejoras incrementales tan pronto como estén listas.</p>
</li>
<li><p>Límites de trabajo en progreso (WIP): Scrum establece límites estrictos sobre la cantidad de trabajo que puede estar en progreso en un momento dado, mientras que Kanban tiene límites WIP más relajados y se enfoca en administrar el flujo.</p>
</li>
<li><p>Gestión de cambios <em>(Change management)</em>: Scrum tiene procesos definidos para introducir cambios en el <em>product backlog</em>, mientras que Kanban tiene un enfoque más flexible para cambiar y fomenta la mejora continua.</p>
</li>
<li><p>Planificación: Scrum tiene un proceso definido de planificación de sprint, mientras que Kanban no tiene eventos de planificación formales y se enfoca en entregar valor lo antes posible.</p>
</li>
<li><p>Estructura del equipo: Scrum requiere un equipo multifuncional con roles definidos, mientras que Kanban tiene una estructura de equipo más flexible y puede ser utilizado por equipos de cualquier tamaño y composición.</p>
</li>
<li><p>Enfoque: Scrum se enfoca en entregar un incremento de producto entregable al final de cada sprint, mientras que Kanban se enfoca en la entrega continua y en mejorar el flujo de valor para los clientes.</p>
</li>
<li><p>Releases en producción: Aunque ninguno define en qué momentos se debe desplegar nuevas funcionalidades a ambientes productivos, es común que en Scrum se haga al final de cada sprint, mientras que en Kanban se hace en cualquier momento siempre y cuando la tarea haya llegado al final de su proceso.</p>
</li>
</ol>
<h2 id="heading-beneficios-de-kanban-sobre-scrum">Beneficios de Kanban sobre scrum</h2>
<ol>
<li><p>Flexibilidad: Kanban es una metodología más flexible, que permite a los equipos adaptarse a los cambios en los requisitos y priorizar las tareas según sea necesario.</p>
</li>
<li><p>Visualización: el tablero visual utilizado en Kanban proporciona una descripción general fácil de entender de los elementos de trabajo y su progreso, lo que facilita la identificación de cuellos de botella y la gestión del flujo de trabajo.</p>
</li>
<li><p>Mejora continua: Kanban pone un fuerte énfasis en la mejora continua, lo que facilita la identificación de áreas de mejora y la realización de cambios en el proceso según sea necesario.</p>
</li>
<li><p>Sin casillas de tiempo <em>(No time boxes)</em>: Kanban no tiene casillas de tiempo <em>(time boxes)</em>, por lo que no hay presión para completar una cierta cantidad de trabajo dentro de un marco de tiempo específico.</p>
</li>
<li><p>Sin planificación de Sprint: Kanban no tiene eventos formales de planificación de Sprint, lo que lo convierte en un enfoque más ligero que puede ser menos perjudicial para el trabajo del equipo.</p>
</li>
<li><p>Menores gastos generales: Kanban tiene menos gastos generales en comparación con Scrum, con menos reuniones, ceremonias y requisitos de documentación.</p>
</li>
<li><p>Riesgo reducido: Kanban reduce el riesgo de desarrollar características que no son necesarias o que no satisfacen las necesidades del cliente, ya que permite una priorización más flexible de los elementos de trabajo.</p>
</li>
<li><p>Mejor visibilidad: el tablero visual utilizado en Kanban proporciona una mayor visibilidad del progreso de los elementos de trabajo y el estado general del proyecto, lo que facilita que las partes interesadas entiendan lo que está sucediendo y qué esperar.</p>
</li>
</ol>
<h2 id="heading-beneficios-de-scrum-sobre-kanban">Beneficios de Scrum sobre Kanban</h2>
<ol>
<li><p>Proceso estructurado: Scrum proporciona un proceso estructurado y repetible para entregar valor, que puede ayudar a los equipos a ser más eficientes y consistentes en su trabajo.</p>
</li>
<li><p>Roles claros: Scrum define roles claros para los miembros del equipo, lo que ayuda a garantizar que todos conozcan sus responsabilidades y cómo encajan en el proceso general.</p>
</li>
<li><p>Cajas de tiempo <em>(Time boxes)</em>: Scrum utiliza cajas de tiempo (sprints) para enfocar los esfuerzos del equipo y garantizar que el trabajo se complete de manera oportuna.</p>
</li>
<li><p>Planificación de Sprint: Scrum tiene un proceso de planificación de Sprint definido que ayuda al equipo a comprender qué trabajo se necesita y cómo priorizarlo.</p>
</li>
<li><p>Revisiones periódicas: Scrum incluye retrospectivas periódicas de sprint que permiten al equipo reflexionar sobre lo que salió bien y lo que se puede mejorar.</p>
</li>
<li><p>Equipos multifuncionales: Scrum requiere equipos multifuncionales, lo que puede conducir a una mayor colaboración, intercambio de conocimientos y una mejor alineación en toda la organización.</p>
</li>
<li><p>Incrementos de productos potencialmente entregables: Scrum se enfoca en entregar un incremento de productos que se pueden entregar al final de cada sprint, lo que ayuda a garantizar que el equipo entregue valor al cliente de manera regular.</p>
</li>
<li><p>Mejora continua: Scrum también hace hincapié en la mejora continua, lo que facilita la identificación de áreas de mejora y la realización de cambios en el proceso a lo largo del tiempo.</p>
</li>
<li><p>Mejor gestión de riesgos: Scrum ayuda a gestionar los riesgos al garantizar que el equipo esté trabajando primero en las tareas más importantes y al permitir que el equipo se adapte a los cambios en los requisitos y prioridades durante cada sprint.</p>
</li>
</ol>
<h2 id="heading-pensamientos-finales">Pensamientos finales</h2>
<p>Realmente no existe una metodología ganadora, es importante entender las principales diferencias y beneficios de una metodología sobre la otra, luego tomarse el tiempo necesario para evaluar nuestras necesidades e implementar la metodología que más nos conviene.</p>
<p>En mi experiencia he trabajado en empresas que tienen ambas metodologías implementadas, y muchas veces utilizan Scrum cuando son proyectos completamente nuevos y Kanban en proyectos que están en modo "mantenimiento".</p>
<p>Sin embargo, no es una regla que esa deba ser la implementación, como he mencionado, es importante entender las necesidades que tenemos en nuestra empresa, nuestros clientes (internos o externos), nuestras capacidades y recursos con los que contamos.</p>
]]></content:encoded></item><item><title><![CDATA[Los 10 selectores de CSS que debes conocer]]></title><description><![CDATA[Los selectores de CSS se utilizan para seleccionar y diseñar elementos HTML en una página web. Son la piedra angular de CSS y son esenciales para crear páginas web dinámicas y visualmente atractivas. Hay numerosos selectores de CSS disponibles, pero ...]]></description><link>https://jfbarrios.com/los-10-selectores-de-css-que-debes-conocer</link><guid isPermaLink="true">https://jfbarrios.com/los-10-selectores-de-css-que-debes-conocer</guid><category><![CDATA[CSS]]></category><category><![CDATA[selectors]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Wed, 01 Feb 2023 18:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/NzERTNpnaDw/upload/7f9428b40a8b6df1bfb74cca833e25df.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Los selectores de CSS se utilizan para seleccionar y diseñar elementos HTML en una página web. Son la piedra angular de CSS y son esenciales para crear páginas web dinámicas y visualmente atractivas. Hay numerosos selectores de CSS disponibles, pero los siguientes 10 son los más utilizados:</p>
<h2 id="heading-selector-de-elementos">Selector de elementos</h2>
<p>El selector de elementos selecciona elementos en función de su nombre de etiqueta. Por ejemplo, para añadir estilos a todos los elementos h1, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">color</span>: blue;
}
</code></pre>
<h2 id="heading-selector-de-clase">Selector de clase</h2>
<p>El selector de clase selecciona elementos en función de su atributo de clase. Las clases se indican con un punto <code>(.)</code> en el código CSS, seguido del nombre de la clase. Por ejemplo, para añadir estilos a todos los elementos con la clase "<strong>highlight</strong>", usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.highlight</span> {
    <span class="hljs-attribute">background-color</span>: yellow;
}
</code></pre>
<h2 id="heading-selector-de-id">Selector de ID</h2>
<p>El selector de ID selecciona elementos en función de su atributo de ID. Los ID se indican con un hash <code>(#)</code> en el código CSS, seguido del nombre del ID. Los ID son exclusivos de una página y solo se pueden usar una vez. Por ejemplo, para añadir estilos a el elemento con el ID "<strong>header</strong>", usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#header</span> {
    <span class="hljs-attribute">background-color</span>: gray;
}
</code></pre>
<h2 id="heading-selector-universal">Selector universal</h2>
<p>El selector universal selecciona todos los elementos de una página. Se indica con un asterisco <code>(*)</code> en el código CSS. Por ejemplo, para añadir estilos a todos los elementos de una página con la fuente "Arial", usaría el siguiente código CSS:</p>
<pre><code class="lang-css">* {
    <span class="hljs-attribute">font-family</span>: Arial;
}
</code></pre>
<h2 id="heading-selector-de-atributos">Selector de atributos</h2>
<p>El selector de atributos selecciona elementos en función de sus atributos y valores de atributos. Por ejemplo, para añadir estilos a todos los elementos "input" con un atributo "<strong>type</strong>" igual a "<strong>send</strong>", usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"send"</span>]</span> {
    <span class="hljs-attribute">background-color</span>: green;
}
</code></pre>
<h2 id="heading-selector-de-hermanos-adyacentes">Selector de hermanos adyacentes</h2>
<p>El selector de hermanos adyacentes selecciona un elemento que está directamente después de otro elemento. El selector se indica con un signo más <code>(+)</code> en el código CSS. Por ejemplo, para añadir estilos a un elemento de tipo párrafo que esta inmediatamente después de un elemento h2, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h2</span> + <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
}
</code></pre>
<h2 id="heading-selector-de-descendientes">Selector de descendientes</h2>
<p>El selector de descendientes (sin importar el nivel de descendencia) selecciona elementos que son descendientes de un elemento especificado. Los descendientes son elementos que están anidados dentro de otro elemento. Por ejemplo, para añadir estilos a todos los elementos de "span" dentro de un párrafo, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">span</span> {
    <span class="hljs-attribute">color</span>: red;
}
</code></pre>
<h2 id="heading-selector-de-ninos-child">Selector de niños (child)</h2>
<p>El selector de niños (child) selecciona elementos que son descendientes directos de un elemento específico. Los elementos secundarios son elementos que están anidados directamente dentro de otro elemento. Por ejemplo, para añadir estilos solo a los elementos de la lista de primer nivel dentro de una lista desordenada, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">ul</span> &gt; <span class="hljs-selector-tag">li</span> {
    <span class="hljs-attribute">background-color</span>: lightblue;
}
</code></pre>
<h2 id="heading-selector-de-pseudoclase">Selector de pseudoclase</h2>
<p>El selector de pseudoclase selecciona elementos en función de su estado o ubicación. Por ejemplo, para añadir estilos a todos los enlaces que han sido visitados, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:visited</span> {
    <span class="hljs-attribute">color</span>: purple;
}
</code></pre>
<h2 id="heading-selector-de-pseudoelementos">Selector de pseudoelementos</h2>
<p>El selector de pseudoelementos selecciona una parte específica de un elemento. Por ejemplo, para aplicar estilo a la primera letra de un párrafo, usaría el siguiente código CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::first-letter</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">36px</span>;
}
</code></pre>
<p>En conclusión, estos 10 selectores de CSS son los más utilizados y forman la base para diseñar páginas web. Comprender y dominar estos selectores es un paso esencial para convertirse en un desarrollador web experto.</p>
]]></content:encoded></item><item><title><![CDATA[Top 10 de las mejores características de ES6]]></title><description><![CDATA[ECMAScript 6, también conocido como ECMAScript 2015, fue una actualización importante del lenguaje JavaScript y trajo muchas funciones y mejoras nuevas. Estas diez características son algunas de las adiciones más utilizadas e importantes al lenguaje....]]></description><link>https://jfbarrios.com/top-10-de-las-mejores-caracteristicas-de-es6</link><guid isPermaLink="true">https://jfbarrios.com/top-10-de-las-mejores-caracteristicas-de-es6</guid><category><![CDATA[ES6]]></category><category><![CDATA[ecmascript]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Sun, 29 Jan 2023 23:24:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lud4OaUCP4Q/upload/b1fe98416eb31a6c8ce08ce31ceba4b6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>ECMAScript 6, también conocido como ECMAScript 2015, fue una actualización importante del lenguaje JavaScript y trajo muchas funciones y mejoras nuevas. Estas diez características son algunas de las adiciones más utilizadas e importantes al lenguaje.</p>
<h2 id="heading-1-let-y-const-la-introduccion-de-variables-de-ambito-de-bloque">1. Let y Const: La introducción de variables de ámbito de bloque.</h2>
<p>En JavaScript, una variable <code>let</code> es una variable de ámbito de bloque declarada con la palabra clave <code>let</code>.</p>
<p>La principal diferencia entre var y let es el ámbito en el que se declaran. Las variables declaradas con <code>var</code> tienen un ámbito de función, lo que significa que son accesibles dentro de toda la función en la que se declaran. Por otro lado, las variables declaradas con <code>let</code> tienen alcance de bloque, lo que significa que solo son accesibles dentro del bloque en el que se declaran.</p>
<p>He aquí un ejemplo para demostrar la diferencia:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">example</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) {
    <span class="hljs-keyword">let</span> x = <span class="hljs-number">10</span>;
    <span class="hljs-keyword">var</span> y = <span class="hljs-number">20</span>;
  }
  <span class="hljs-built_in">console</span>.log(x);  <span class="hljs-comment">// ReferenceError: x is not defined</span>
  <span class="hljs-built_in">console</span>.log(y);  <span class="hljs-comment">// Output: 20</span>
}

example();
</code></pre>
<p>En este ejemplo, la variable <code>let</code> <code>x</code> solo es accesible dentro del bloque en el que se declara (la declaración <code>if</code>), mientras que la variable <code>var</code> <code>y</code> es accesible a lo largo de toda la función. Intentar acceder a <code>x</code> fuera de su bloque dará como resultado un error de referencia <code>ReferenceError</code>.</p>
<h2 id="heading-2-funciones-de-flechas-sintaxis-abreviada-para-crear-funciones">2. Funciones de flechas: sintaxis abreviada para crear funciones.</h2>
<p>Las funciones de flecha, también conocidas como <code>fat arrow functions</code>, son una sintaxis abreviada para definir funciones en JavaScript.</p>
<p>Las funciones de flecha tienen la siguiente sintaxis:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Basic arrow function with one argument and one statement</span>
<span class="hljs-keyword">const</span> square = <span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x * x;
<span class="hljs-built_in">console</span>.log(square(<span class="hljs-number">3</span>));  <span class="hljs-comment">// Output: 9</span>

<span class="hljs-comment">// Arrow function with multiple arguments and multiple statements</span>
<span class="hljs-keyword">const</span> multiply = <span class="hljs-function">(<span class="hljs-params">x, y</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> result = x * y;
  <span class="hljs-keyword">return</span> result;
};
<span class="hljs-built_in">console</span>.log(multiply(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Output: 12</span>
</code></pre>
<p>Las funciones de flecha tienen una serie de beneficios, que incluyen:</p>
<ol>
<li><p>Sintaxis más corta: las funciones de flecha son más cortas y fáciles de leer en comparación con las expresiones de funciones tradicionales.</p>
</li>
<li><p>Retorno implícito: si una función de flecha tiene una sola expresión, el valor de retorno se devuelve implícitamente. No es necesario incluir la palabra clave de retorno.</p>
</li>
<li><p>Lexical <code>this</code>: las funciones de flecha heredan el valor de <code>this</code> del contexto que las rodea, lo que las hace ideales para usar en devoluciones de llamada y controladores de eventos.</p>
</li>
<li><p>No se pueden usar como constructores: las funciones de flecha no se pueden usar con el operador <code>new</code> para crear objetos, lo que ayuda a evitar algunos errores comunes.</p>
</li>
</ol>
<p>En general, las funciones de flecha son una característica poderosa y conveniente de JavaScript y se usan ampliamente en el código moderno.</p>
<h2 id="heading-3-template-literals-interpolacion-de-cadenas-y-cadenas-multilinea">3. Template literals: interpolación de cadenas y cadenas multilínea.</h2>
<p>Brindan una forma más conveniente de crear cadenas que incluyen contenido dinámico.</p>
<p>Los literales de plantilla usan acentos graves (```) en lugar de comillas simples o dobles para definir literales de cadena. Las expresiones se pueden incluir dentro de un literal de plantilla utilizando la sintaxis <strong>${expresión}</strong>.</p>
<p>Aquí hay un ejemplo del uso de literales de plantilla:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> name = <span class="hljs-string">'John'</span>;
<span class="hljs-keyword">const</span> message = <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;
<span class="hljs-built_in">console</span>.log(message);  <span class="hljs-comment">// Output: Hello, John!</span>
</code></pre>
<p>También admiten cadenas de varias líneas, lo que puede ser útil para crear cadenas más complejas:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> multiLine = <span class="hljs-string">`This is a
multiline string.`</span>;
<span class="hljs-built_in">console</span>.log(multiLine);
</code></pre>
<p>Salida:</p>
<pre><code class="lang-bash">This is a
multiline string.
</code></pre>
<h2 id="heading-4-desestructuracion-extraccion-de-valores-de-matrices-u-objetos">4. Desestructuración: extracción de valores de matrices u objetos.</h2>
<p>La desestructuración en JavaScript es una función que le permite extraer valores de matrices u objetos y asignarlos a variables. Esto proporciona una forma conveniente y eficiente de desempaquetar valores de matrices y objetos, lo que facilita el trabajo con datos de manera estructurada.</p>
<p>Aquí hay un ejemplo de desestructuración de una matriz:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> [first, second, third] = numbers;
<span class="hljs-built_in">console</span>.log(first, second, third);  <span class="hljs-comment">// Output: 1 2 3</span>
</code></pre>
<p>Aquí hay un ejemplo de desestructuración de un objeto:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };
<span class="hljs-keyword">const</span> { name, age } = person;
<span class="hljs-built_in">console</span>.log(name, age);  <span class="hljs-comment">// Output: John 30</span>
</code></pre>
<p>La desestructuración también se puede utilizar para extraer valores de matrices y objetos anidados:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> data = {
  <span class="hljs-attr">person</span>: { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> },
  <span class="hljs-attr">numbers</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
};
<span class="hljs-keyword">const</span> { <span class="hljs-attr">person</span>: { name }, <span class="hljs-attr">numbers</span>: [first, second, third] } = data;
<span class="hljs-built_in">console</span>.log(name, first, second, third);  <span class="hljs-comment">// Output: John 1 2 3</span>
</code></pre>
<h2 id="heading-5-parametros-predeterminados-especificacion-de-valores-predeterminados-para-los-parametros-de-funcion">5. Parámetros predeterminados: especificación de valores predeterminados para los parámetros de función.</h2>
<p>Los parámetros predeterminados son una característica de JavaScript que le permite especificar valores predeterminados para los parámetros de la función. Si se llama a una función sin un argumento para un parámetro dado, se usará el valor predeterminado en su lugar. Esto puede ser útil para proporcionar un comportamiento predeterminado para parámetros opcionales y evitar errores causados por argumentos faltantes.</p>
<p>Este es un ejemplo del uso de parámetros predeterminados:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name = <span class="hljs-string">'Guest'</span></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>);
}
greet();  <span class="hljs-comment">// Output: Hello, Guest!</span>
greet(<span class="hljs-string">'John'</span>);  <span class="hljs-comment">// Output: Hello, John!</span>
</code></pre>
<p>En el ejemplo anterior, si se llama a <code>saludar</code> sin un argumento, se usará el valor predeterminado <strong>'Invitado'</strong> para el parámetro de <strong>nombre</strong>. Si se proporciona un argumento, se utilizará en lugar del valor predeterminado.</p>
<p>Los parámetros predeterminados se pueden usar con cualquier tipo de valor, incluidos números, cadenas, matrices y objetos. También pueden ser expresiones o el resultado de una llamada de función.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateSum</span>(<span class="hljs-params">a = <span class="hljs-number">1</span>, b = <span class="hljs-number">2</span></span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-built_in">console</span>.log(calculateSum());  <span class="hljs-comment">// Output: 3</span>
<span class="hljs-built_in">console</span>.log(calculateSum(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Output: 7</span>
</code></pre>
<p>Los parámetros predeterminados son una característica útil en JavaScript, que le permite proporcionar un comportamiento predeterminado para parámetros opcionales y evitar errores causados por argumentos faltantes.</p>
<h2 id="heading-6-operadores-rest-y-spread-combinando-arrays-o-separandolos">6. Operadores Rest y Spread: Combinando arrays o separándolos.</h2>
<p>El operador <code>rest</code> y el operador de <code>spread</code> son dos funciones que se usan para manejar argumentos de una función y manipulación de matrices/objetos.</p>
<p>El operador <code>rest (...)</code> le permite representar un número indefinido de argumentos como una matriz. Se usa en declaraciones de funciones para capturar todos los argumentos pasados a la función, excluyendo los parámetros con nombre.</p>
<p>Aquí hay un ejemplo del uso del operador <code>rest</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">...numbers</span>) </span>{
  <span class="hljs-keyword">return</span> numbers.reduce(<span class="hljs-function">(<span class="hljs-params">total, value</span>) =&gt;</span> total + value, <span class="hljs-number">0</span>);
}
<span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Output: 10</span>
</code></pre>
<p>En el ejemplo anterior, el operador rest <code>...númbers</code> recopila todos los argumentos pasados a la función de suma y los asigna a una matriz de números.</p>
<p>El operador de propagación <code>(...)</code> le permite distribuir los elementos de una matriz o un objeto en una nueva matriz u objeto. También se puede usar para concatenar arreglos o pasar elementos individuales de un arreglo como argumentos separados a una función.</p>
<p>Aquí hay un ejemplo del uso del operador de propagación para concatenar matrices:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> array1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> array2 = [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>];
<span class="hljs-keyword">const</span> concatenated = [...array1, ...array2];
<span class="hljs-built_in">console</span>.log(concatenated);  <span class="hljs-comment">// Output: [1, 2, 3, 4, 5, 6]</span>
</code></pre>
<p>En el ejemplo anterior, el operador de propagación <code>...array1</code> y <code>...array2</code> distribuyen los elementos de <code>array1</code> y <code>array2</code> en una nueva matriz concatenada.</p>
<p>Los operadores <mark>rest</mark> y <mark>spread</mark> brindan una manera conveniente y concisa de manejar argumentos de funciones y manipulación de matrices/objetos en JavaScript, y se usan ampliamente en el código moderno.</p>
<h2 id="heading-7-clases-un-azucar-sintactico-para-la-programacion-orientada-a-objetos">7. Clases: un azúcar sintáctico para la programación orientada a objetos.</h2>
<p>Las clases le permiten definir la estructura de un objeto, incluidas sus propiedades y métodos, y crear varias instancias del mismo objeto con un comportamiento similar.</p>
<p>Aquí hay un ejemplo del uso de una clase en JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }
  sayHello() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, my name is <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>`</span>);
  }
}

<span class="hljs-keyword">const</span> john = <span class="hljs-keyword">new</span> User(<span class="hljs-string">'John'</span>);
john.sayHello();  <span class="hljs-comment">// Output: Hello, my name is John</span>
<span class="hljs-keyword">const</span> jane = <span class="hljs-keyword">new</span> User(<span class="hljs-string">'Jane'</span>);
jane.sayHello();  <span class="hljs-comment">// Output: Hello, my name is Jane</span>
</code></pre>
<p>En el ejemplo anterior, definimos una clase <code>User</code> con un método <code>constructor</code> que establece la propiedad de <code>name</code> de una instancia y un método <code>sayHello</code> que genera un mensaje de saludo. Luego creamos dos instancias de la clase <code>User</code>, <strong>john</strong> y <strong>jane</strong>, y llamamos a sus respectivos métodos <code>sayHello</code>.</p>
<p>Las clases en JavaScript también admiten la herencia, lo que le permite crear una nueva clase basada en una clase existente, con la capacidad de sobreescribir o ampliar sus propiedades y métodos.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Admin</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">constructor</span>(name, role) {
    <span class="hljs-built_in">super</span>(name);
    <span class="hljs-built_in">this</span>.role = role;
  }
  sayHello() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, my name is <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am an <span class="hljs-subst">${<span class="hljs-built_in">this</span>.role}</span>`</span>);
  }
}

<span class="hljs-keyword">const</span> admin = <span class="hljs-keyword">new</span> Admin(<span class="hljs-string">'Admin'</span>, <span class="hljs-string">'administrator'</span>);
admin.sayHello();  <span class="hljs-comment">// Output: Hello, my name is Admin and I am an administrator</span>
</code></pre>
<p>En el ejemplo anterior, definimos una clase <code>Admin</code> que amplía la clase <code>User</code> y agrega una propiedad de <code>rol</code> y una nueva implementación del método <code>sayHello</code>. Luego creamos una instancia de la clase <code>Admin</code>, <strong>admin</strong>, y llamamos a su método <code>sayHello</code>.</p>
<p>Las clases son una función poderosa y flexible en JavaScript, que le permite definir la estructura y el comportamiento de los objetos y admitir la herencia y los patrones de programación orientados a objetos.</p>
<h2 id="heading-8-modulos-forma-estandar-de-organizar-el-codigo-en-unidades-reutilizables">8. Módulos: forma estándar de organizar el código en unidades reutilizables.</h2>
<p>Los módulos en JavaScript son una forma de organizar y reutilizar el código encapsulándolo en unidades reutilizables que se pueden importar y usar en otras partes de una aplicación. Un módulo puede contener variables, funciones, clases y otro código, y puede exponer una interfaz al resto de la aplicación que especifica qué partes del módulo son públicas y accesibles para otro código.</p>
<p>Hay dos formas principales de usar módulos en JavaScript:</p>
<ol>
<li><p>Módulos CommonJS (utilizados en Node.js): un módulo en CommonJS se define como un archivo único que exporta uno o más valores y se puede importar a otros archivos en la aplicación. Las exportaciones son accesibles a otros archivos usando la función require. Aquí hay un ejemplo del uso de módulos CommonJS en Node.js:</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// math.js</span>
 <span class="hljs-built_in">exports</span>.sum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;
 <span class="hljs-built_in">exports</span>.product = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a * b;

 <span class="hljs-comment">// index.js</span>
 <span class="hljs-keyword">const</span> math = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./math'</span>);
 <span class="hljs-built_in">console</span>.log(math.sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));  <span class="hljs-comment">// Output: 3</span>
 <span class="hljs-built_in">console</span>.log(math.product(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Output: 12</span>
</code></pre>
<p> En el ejemplo anterior, el archivo <code>math.js</code> exporta dos funciones, <code>sum</code> y <code>product</code>, que se pueden importar y usar en otros archivos de la aplicación mediante la función <code>require</code>.</p>
</li>
<li><p>Módulos ES6 (compatibles con navegadores modernos y con herramientas como Babel): un módulo en ES6 se define como un archivo único que exporta uno o más valores y se puede importar a otros archivos en la aplicación. Las exportaciones son accesibles a otros archivos utilizando las declaraciones de <code>import</code> y <code>export</code>.</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// math.js</span>
 <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;
 <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> product = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a * b;

 <span class="hljs-comment">// index.js</span>
 <span class="hljs-keyword">import</span> { sum, product } <span class="hljs-keyword">from</span> <span class="hljs-string">'./math'</span>;
 <span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>));  <span class="hljs-comment">// Output: 3</span>
 <span class="hljs-built_in">console</span>.log(product(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>));  <span class="hljs-comment">// Output: 12</span>
</code></pre>
<p> En el ejemplo anterior, el archivo <code>math.js</code> exporta dos valores, <code>sum</code> y <code>product</code>, que se pueden importar y usar en otros archivos de la aplicación mediante la declaración de <code>import</code>.</p>
<p> Los módulos proporcionan una forma de organizar y reutilizar el código en JavaScript, lo que facilita el mantenimiento y el intercambio de código entre diferentes partes de una aplicación. <strong>También ayudan a reducir el tamaño del código en una aplicación al permitirle importar solo las partes de un módulo que se necesitan</strong>.</p>
</li>
</ol>
<h2 id="heading-9-map-and-set-estructuras-de-datos-mejoradas-para-almacenar-colecciones">9. Map and Set: Estructuras de datos mejoradas para almacenar colecciones.</h2>
<p>Map: Es una colección de pares clave-valor. Las claves pueden tener cualquier valor (objetos, primitivas) y no tienen que ser únicas. Los valores en un Map se pueden acceder, agregar o modificar usando las claves.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> myMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-comment">// Añadiendo pares de clave-valor al mapa</span>
myMap.set(<span class="hljs-string">'name'</span>, <span class="hljs-string">'John'</span>);
myMap.set(<span class="hljs-string">'age'</span>, <span class="hljs-number">30</span>);
myMap.set(<span class="hljs-string">'city'</span>, <span class="hljs-string">'New York'</span>);

<span class="hljs-comment">// Obteniendo los valores del mapa</span>
<span class="hljs-built_in">console</span>.log(myMap.get(<span class="hljs-string">'name'</span>)); <span class="hljs-comment">// Output: John</span>
<span class="hljs-built_in">console</span>.log(myMap.get(<span class="hljs-string">'age'</span>)); <span class="hljs-comment">// Output: 30</span>

<span class="hljs-comment">// Revisando el tamaño del map</span>
<span class="hljs-built_in">console</span>.log(myMap.size); <span class="hljs-comment">// Output: 3</span>

<span class="hljs-comment">// Revisar si existe una clave dentro del mapa</span>
<span class="hljs-built_in">console</span>.log(myMap.has(<span class="hljs-string">'name'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-comment">// Eliminando una clave-valor del mapa</span>
myMap.delete(<span class="hljs-string">'city'</span>);
<span class="hljs-built_in">console</span>.log(myMap.has(<span class="hljs-string">'city'</span>)); <span class="hljs-comment">// Output: false</span>
</code></pre>
<p>Set: Es una colección de valores únicos. Los valores pueden ser de cualquier tipo y no tienen que ser del mismo tipo. Le permite almacenar valores únicos en una colección desordenada y proporciona métodos para manipular los valores.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> mySet = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>();

<span class="hljs-comment">// Añadiendo valores al Set</span>
mySet.add(<span class="hljs-number">1</span>);
mySet.add(<span class="hljs-number">2</span>);
mySet.add(<span class="hljs-number">3</span>);
mySet.add(<span class="hljs-number">2</span>); <span class="hljs-comment">// Este valor no se añade debido a que Set no soporta duplicados</span>

<span class="hljs-comment">// Revisando el tamaño del Set</span>
<span class="hljs-built_in">console</span>.log(mySet.size); <span class="hljs-comment">// Output: 3</span>

<span class="hljs-comment">// Revisando si un valor esta presente en el Set</span>
<span class="hljs-built_in">console</span>.log(mySet.has(<span class="hljs-number">2</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-comment">// Removiendo un valor del Set</span>
mySet.delete(<span class="hljs-number">1</span>);
<span class="hljs-built_in">console</span>.log(mySet.has(<span class="hljs-number">1</span>)); <span class="hljs-comment">// Output: false</span>

<span class="hljs-comment">// Iterando sobre los valores del Set</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> value <span class="hljs-keyword">of</span> mySet) {
  <span class="hljs-built_in">console</span>.log(value);
}
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// 2</span>
<span class="hljs-comment">// 3</span>
</code></pre>
<h2 id="heading-10-promesas-una-mejor-manera-de-manejar-el-codigo-asincrono">10. Promesas: una mejor manera de manejar el código asíncrono.</h2>
<p>Las promesas son objetos en JavaScript que representan la eventual finalización o falla de una operación asincrónica. Proporcionan una manera de manejar los resultados de las operaciones asincrónicas (como las solicitudes de red) de una manera más fácil de leer y mantener.</p>
<p>Una Promesa puede estar en uno de tres estados:</p>
<ol>
<li><p>Pendiente (<em>Pending</em>): estado inicial, ni cumplida ni rechazada.</p>
</li>
<li><p>Cumplido (<em>Fulfilled</em>): lo que significa que la operación se completó con éxito.</p>
</li>
<li><p>Rechazado (Rejected): significa que la operación falló.</p>
</li>
</ol>
<p>Puede adjuntar funciones de devolución de llamada a una Promesa usando el método <code>then</code> para manejar el cumplimiento y el método <code>catch</code> para manejar el rechazo.</p>
<p>Aquí hay un ejemplo del uso de una Promesa en JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> myPromise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> result = doSomethingAsynchronously();
  <span class="hljs-keyword">if</span> (result) {
    resolve(result);
  } <span class="hljs-keyword">else</span> {
    reject(<span class="hljs-built_in">Error</span>(<span class="hljs-string">'Operation failed'</span>));
  }
});

myPromise
  .then(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
    <span class="hljs-comment">// handle success</span>
  })
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
    <span class="hljs-comment">// handle error</span>
  });
</code></pre>
]]></content:encoded></item><item><title><![CDATA[3 formas de obtener el Fibonacci de un número en JavaScript]]></title><description><![CDATA[Un número Fibonacci, usualmente con notación f(n), es la suma de los dos números fibonacci que le preceden. Esta sucesión empieza con f(0) = 0, f(1) = 1, f(2) = f(1) + f(0) hasta f(x) = f(x-1) + f(x-2).
En este artículo veremos tres formas diferentes...]]></description><link>https://jfbarrios.com/3-formas-de-obtener-el-fibonacci-de-un-numero-en-javascript</link><guid isPermaLink="true">https://jfbarrios.com/3-formas-de-obtener-el-fibonacci-de-un-numero-en-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Fri, 08 Apr 2022 06:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/YfCVCPMNd38/upload/v1649456724318/B6NEB_etp.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Un número Fibonacci, usualmente con notación <code>f(n)</code>, es la suma de los dos números fibonacci que le preceden. Esta sucesión empieza con <code>f(0) = 0</code>, <code>f(1) = 1</code>, <code>f(2) = f(1) + f(0)</code> hasta <code>f(x) = f(x-1) + f(x-2)</code>.</p>
<p>En este artículo veremos tres formas diferentes de encontrar un el resultado de aplicar la sucesión a un determinado número.</p>
<h2 id="heading-recursion">Recursión</h2>
<p>Si usamos un sistema de recursión para calcular resultado de fibonacci para determinado número, por ejemplo 5, lo que obtendríamos es algo parecido a esto:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649454539633/lgBfCuCOJ.png" alt="Fibonacci Diagrams.drawio.png" /></p>
<p><strong>Algoritmo</strong></p>
<ol>
<li>Debemos revisar que el número <code>n</code> que le estamos pasando a la función es igual o menor que <code>1</code>, si este es el caso tenemos que devolver <code>n</code> como el resultado de la función.</li>
<li>En caso contrario, la función se volverá a llamar a sí misma, pasándose como argumento el cálculo de <code>n-1</code> y <code>n-2</code> respectivamente, posteriormente devolverá como su resultado la suma de ambas invocaciones.</li>
</ol>
<p><strong>Implementación</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> fib = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">n</span>) </span>{
    <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;

    <span class="hljs-keyword">return</span> fib(n<span class="hljs-number">-1</span>) + fib(n<span class="hljs-number">-2</span>);
}
</code></pre>
<p><strong>Complejidad (Time Complexity)</strong> </p>
<p>No entraré en detalle sobre cómo calcular la complejidad computacional, pero les dejo acá que es: <code>2^n</code>, por lo que podemos ver que entre más grande sea el número, crece enormemente la cantidad de recurso computacional.</p>
<h2 id="heading-programacion-dinamica-top-down-con-memorizacion">Programación Dinámica Top-Down con memorización</h2>
<p>El primer enfoque de programación dinámica que quiero que veamos es de <code>top-down</code>. La idea aquí es similar al enfoque recursivo, pero la diferencia es que guardaremos las soluciones a los subproblemas que encontremos.</p>
<p>De esta forma, si nos encontramos con el mismo subproblema más de una vez, podemos usar nuestra solución guardada en lugar de tener que volver a calcularla. Esto nos permite calcular cada subproblema exactamente una vez.</p>
<p>Esta técnica de programación dinámica se llama memorización. Podemos ver cómo nuestro árbol de subproblemas se reduce cuando usamos la memorización:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649454791812/eEso2vf6q.png" alt="Fibonacci Diagrams.drawio memorización.png" /></p>
<p><strong>Algoritmo</strong></p>
<ol>
<li>Debemos revisar que el número <code>n</code> que le estamos pasando a la función es igual o menor que <code>1</code>, si este es el caso tenemos que devolver <code>n</code> como el resultado de la función.</li>
<li>En caso contrario, revisaremos si el subproblema ya ha sido solucionado con anterioridad, de no ser así, entonces procederemos a realizar el mismo proceso que utilizamos en la recursividad y guardaremos el resultado</li>
<li>Devolveremos el resultado que hemos guardado, ya sea porque se haya computado por primera vez o por que ya lo hayamos calculado previamente.</li>
</ol>
<p><strong>Implementación</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> fib = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">n</span>) </span>{
    <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>(); <span class="hljs-comment">// creamos un mapa para guardar los valores</span>

    <span class="hljs-keyword">const</span> dp = <span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (x &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> x;

        <span class="hljs-keyword">if</span> (!map.has(x)) { <span class="hljs-comment">// si NO hemos calculado el resultado</span>
            map.set(x, dp(x<span class="hljs-number">-1</span>) + dp(x<span class="hljs-number">-2</span>)) <span class="hljs-comment">// lo calculamos y guardamos el valor</span>
        }

        <span class="hljs-keyword">return</span> map.get(x);
    }

    <span class="hljs-keyword">return</span> dp(n);
};
</code></pre>
<p><strong>Complejidad</strong></p>
<p>Para este escenario la complejidad será de <code>O(n)</code>, una complejidad mucho menor comparada con la de recursividad.</p>
<h2 id="heading-programacion-dinamica-bottom-up">Programación Dinámica Bottom-Up</h2>
<p>En el enfoque de programación dinámica Bottom-Up, lo que buscamos es solucionar los subproblemas en un orden diferente, es decir, primero resolvemos <code>f(2)</code>, luego <code>f(3)</code>, luego <code>f(4)</code> y así hasta llegar a <code>f(n)</code>. De esta forma no tenemos que memorizar nada, puesto que únicamente calcularemos aquellos subproblemas que son necesarios.</p>
<p><strong>Algoritmo</strong></p>
<ol>
<li>Tendremos un array donde iremos almacenando los valores de cada subproblema, este lo inicializaremos con los resultados base <code>0, 1</code>.</li>
<li>Recorreremos desde la posición 2 hasta llegar a <code>n</code> (incluyéndola) para añadir la solución de cada subproblema.</li>
<li>Devolveremos luego nuestro array en la última posición.</li>
</ol>
<p><strong>Implementación</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> fib = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">n</span>) </span>{
    <span class="hljs-keyword">const</span> sol = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>];

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">2</span>; i&lt;= n; i++) {
        sol[i] = sol[i <span class="hljs-number">-1</span>] + sol[i - <span class="hljs-number">2</span>];
    }

    <span class="hljs-keyword">return</span> sol[n];
};
</code></pre>
<p><strong>Complejidad</strong></p>
<p>En este caso la complejidad computacional sigue siendo de <code>O(n)</code>.</p>
<h2 id="heading-bonus">Bonus</h2>
<p>El cálculo de complejidad no solo se debe considerar a nivel computacional, también a nivel de uso de memoria, por lo que si vemos, por ejemplo, la solución <code>Bottom-Up</code>, no es óptima puesto que hemos guardado en memoria datos predecesores que no son necesarios.</p>
<p>Es más fácil visualizarlo si pensamos en que queremos el fibonacci de 10, tendríamos algo como <code>[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]</code>, pero realmente para tener el fibonacci de <code>10</code> solo es necesario tener en memoria los últimos 2 valores <code>21</code> y <code>34</code>.</p>
<p><strong>Implementación</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> fib = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">n</span>) </span>{

    <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;

    <span class="hljs-keyword">let</span> prev2 = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">let</span> prev1 = <span class="hljs-number">1</span>;
    <span class="hljs-keyword">let</span> c = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">2</span>; i&lt;= n; i++) {
        c = prev1 + prev2;
        prev2 = prev1;
        prev1 = c;
    }

    <span class="hljs-keyword">return</span> c;
};
</code></pre>
<h2 id="heading-conclusiones">Conclusiones</h2>
<p>Hemos llegado hasta el final del artículo, déjame saber qué te ha parecido las soluciones, ¿cambiarías algo?, ¿hay algo que no entiendes?</p>
]]></content:encoded></item><item><title><![CDATA[4 formas de medir el performance de tu código en JavaScript]]></title><description><![CDATA[Aprender a medir el performance de ciertos piezas de código resulta ser algo sumamente importante cuando hablamos de aplicaciones que empiezan a tener alto tráfico de uso, o son muy grandes. Sin dejar de lado el hecho de que siempre es importante que...]]></description><link>https://jfbarrios.com/4-formas-de-medir-el-performance-de-tu-codigo-en-javascript</link><guid isPermaLink="true">https://jfbarrios.com/4-formas-de-medir-el-performance-de-tu-codigo-en-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[performance]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Mon, 14 Mar 2022 01:39:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647221893535/D1NGQOm7c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Aprender a medir el performance de ciertos piezas de código resulta ser algo sumamente importante cuando hablamos de aplicaciones que empiezan a tener alto tráfico de uso, o son muy grandes. Sin dejar de lado el hecho de que siempre es importante que tengamos estos conceptos para qué nos ayude en nuestra carrera profesional.</p>
<h2 id="heading-usando-jsbench">Usando JSBen.ch</h2>
<p>Una de las formas más sencillas y simples es utilizar aplicaciones en línea que nos apoyen con esta tarea, particularmente me encanta <a target="_blank" href="https://jsben.ch/">JSBen.ch</a>.</p>
<p>En este sitio podemos añadir <code>n</code> cantidad de bloques de código, el sitio los ejecutará <code>n</code> cantidad de veces y dará un resultado sobre qué bloque de código es más eficiente.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647219810045/szWpmPth5.png" alt="jsbench.png" /></p>
<p>Acá te dejo un ejemplo de dos funciones que calculan si un número es palíndromo o no, en esta podrás ver cuál es más eficiente y en qué porcentaje, <a target="_blank" href="https://jsben.ch/Ghiid">jsben.ch/Ghiid</a>.</p>
<h2 id="heading-utilizando-consoletime-y-consoletimeend">Utilizando <code>console.time</code> y <code>console.timeEnd</code></h2>
<p>En este caso, deberás de invocar la función <code>console.time</code> pasándole cómo argumento un <code>string</code> que es un identificador, el sistema empezará a llevar un tiempo hasta que llames a la función <code>console.timeEnd</code> usando el mismo identificador.</p>
<p>Ejemplo</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> isPalindrome = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x</span>) </span>{
  <span class="hljs-keyword">if</span> (x &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">const</span> str = <span class="hljs-string">""</span> + x;
  <span class="hljs-keyword">const</span> l = str.length;

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; l / <span class="hljs-number">2</span>; i++) {
    <span class="hljs-keyword">if</span> (str[i] !== str[l - i - <span class="hljs-number">1</span>]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
};

<span class="hljs-built_in">console</span>.time(<span class="hljs-string">'performance'</span>);
isPalindrome(<span class="hljs-number">111111111</span>);
isPalindrome(<span class="hljs-number">101</span>);
isPalindrome(<span class="hljs-number">-121</span>);
<span class="hljs-built_in">console</span>.timeEnd(<span class="hljs-string">'performance'</span>); <span class="hljs-comment">// Salida: performance: 0.048095703125 ms</span>
</code></pre>
<h2 id="heading-utilizando-performancenow">Utilizando <code>performance.now</code></h2>
<p>El método <code>performance.now()</code> devuelve un <code>DOMHighResTimeStamp (en-US)</code>, medido en <strong>milisegundos</strong>, con una precisión de cinco milésimas de segundo (5 microsegundos).</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> isPalindrome = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{
    <span class="hljs-keyword">const</span> str = <span class="hljs-string">""</span>+x;

    <span class="hljs-keyword">return</span> str === str.split(<span class="hljs-string">""</span>).reverse().join(<span class="hljs-string">""</span>)
};

<span class="hljs-keyword">const</span> t0 = performance.now();
isPalindrome(<span class="hljs-number">111111111</span>);
isPalindrome(<span class="hljs-number">101</span>);
isPalindrome(<span class="hljs-number">-121</span>);
<span class="hljs-keyword">const</span> t1 = performance.now();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"La llamada a isPalindrome tardó "</span> + (t1 - t0) + <span class="hljs-string">" milisegundos."</span>);
</code></pre>
<h2 id="heading-utilizando-la-libreria-de-benchmark">Utilizando la librería de <code>benchmark</code></h2>
<p>Con esta librería podemos ejecutar pruebas parecidas a la de <code>JSBen.ch</code> pero directamente en nuestra computadora, veamos un ejemplo:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Importamos la librería</span>
<span class="hljs-keyword">import</span> Benchmark <span class="hljs-keyword">from</span> <span class="hljs-string">"benchmark"</span>;

<span class="hljs-comment">// Creamos una suite de pruebas</span>
<span class="hljs-keyword">var</span> suite = <span class="hljs-keyword">new</span> Benchmark.Suite();

suite.add(<span class="hljs-string">"Bloque 1"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
<span class="hljs-keyword">var</span> isPalindrome = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x</span>) </span>{
  <span class="hljs-comment">// código de la función 1</span>
};

isPalindrome(<span class="hljs-number">111111111</span>);
isPalindrome(<span class="hljs-number">101</span>);
isPalindrome(<span class="hljs-number">-121</span>);
})
.add(<span class="hljs-string">"Bloque 2"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{

<span class="hljs-keyword">var</span> isPalindrome = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x</span>) </span>{
  <span class="hljs-comment">// código de la función 2</span>
};

isPalindrome(<span class="hljs-number">111111111</span>);
isPalindrome(<span class="hljs-number">101</span>);
isPalindrome(<span class="hljs-number">-121</span>);
})
.on(<span class="hljs-string">"cycle"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">String</span>(event.target));
})
.on(<span class="hljs-string">"complete"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"El más rápido es "</span> + <span class="hljs-built_in">this</span>.filter(<span class="hljs-string">"fastest"</span>).map(<span class="hljs-string">"name"</span>));
})
.run({ <span class="hljs-attr">async</span>: <span class="hljs-literal">true</span> });
</code></pre>
<h2 id="heading-conclusiones">Conclusiones</h2>
<p>Todas las opciones son válidas, sin embargo, recomiendo utilizar más <code>JSBen.ch</code> o <code>benchmark</code> puesto que nos dan resultados más exactos ya que corren varias veces las pruebas y realizan estadísticas para dar datos más certeros.</p>
]]></content:encoded></item><item><title><![CDATA[¿Todo en JavaScript es un objeto?]]></title><description><![CDATA[Hace unos días, un seguidor de Laserants.com, hizo la pregunta de si una función era un objeto. Mi respuesta fue en torno a explicar cómo casi todo es un objeto en JavaScript. He acá una clasificación de los types en JavaScript:

Primitivos (cadena, ...]]></description><link>https://jfbarrios.com/todo-en-javascript-es-un-objeto</link><guid isPermaLink="true">https://jfbarrios.com/todo-en-javascript-es-un-objeto</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Tue, 08 Mar 2022 13:56:49 GMT</pubDate><content:encoded><![CDATA[<p>Hace unos días, un seguidor de <a target="_blank" href="https://laserants.com">Laserants.com</a>, hizo la pregunta de si una función era un objeto. Mi respuesta fue en torno a explicar cómo casi todo es un objeto en JavaScript. He acá una clasificación de los <code>types</code> en JavaScript:</p>
<ul>
<li><strong>Primitivos (cadena, número, nulo, booleano, indefinido, símbolo)</strong>: estos son tipos de datos inmutables. No son objetos, no tienen métodos y se almacenan en memoria por valor.</li>
<li><strong>No primitivos (funciones, matrices y objetos)</strong>: estos son tipos de datos mutables. Son objetos y se almacenan en memoria por referencia.</li>
</ul>
<p>##¿Qué es un objeto?
La clase <code>Object</code> representa uno de los <strong>tipos de datos</strong> de JavaScript. Se utiliza para almacenar varias colecciones con clave y entidades más complejas. Podemos decir que en JavaScript, un objeto es un entidad independiente con propiedades y tipos. </p>
<p>Para crear un objeto podemos hacer algo como esto:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> obj = {
  <span class="hljs-attr">propiedad1</span>: <span class="hljs-string">'Valor 1'</span>,
  <span class="hljs-attr">propiedad2</span>: <span class="hljs-string">'Valor2'</span>
}
</code></pre>
<p>Ahora vamos a añadir una nueva propiedad al objeto</p>
<pre><code class="lang-javascript">obj.propiedad3 = <span class="hljs-string">'Valor 3'</span>;
</code></pre>
<h2 id="heading-arrays-como-objetos">Arrays como objetos</h2>
<p>Un array es un objeto en JavaScript, y lo podemos demostrar de dos formas:</p>
<ol>
<li>Usando typeof:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>];
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> a);  <span class="hljs-comment">// Salida: 'object'</span>
</code></pre>
<ol>
<li>Añadiendo más propiedades o claves</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>];
arr.saludar = <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hola"</span>);  <span class="hljs-comment">// Añadiendo la propiedad saludar al objeto arr.</span>

<span class="hljs-built_in">console</span>.log(arr.length); <span class="hljs-comment">// Salida: 3</span>
<span class="hljs-built_in">console</span>.log(arr.saludar); <span class="hljs-comment">// Salida: hola</span>
<span class="hljs-built_in">console</span>.log(arr); <span class="hljs-comment">// Salida: (3) [1, 2, 3, saludar: ƒ]</span>
</code></pre>
<h2 id="heading-funciones-como-objeto">Funciones como Objeto</h2>
<p>Ahora veamos el caso de un <code>Array</code> con este ejemplo, primero crearemos una función</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saludar</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hola!"</span>);
}
</code></pre>
<p>Ahora le añadiremos más propiedades</p>
<pre><code class="lang-javascript">saludar.nombre = <span class="hljs-string">"Fernando"</span>; 
saludar.conNombre = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hola, <span class="hljs-subst">${<span class="hljs-built_in">this</span>.nombre}</span>!`</span>)
}
</code></pre>
<p>Imprimamos unos logs</p>
<pre><code class="lang-javascript">saludar() <span class="hljs-comment">// Salida: Hola!</span>
<span class="hljs-built_in">console</span>.log(saludar.nombre); <span class="hljs-comment">// Salida: Fernando</span>
saludar.conNombre() <span class="hljs-comment">// Salida: Hola, Fernando!</span>
</code></pre>
<h2 id="heading-string">String</h2>
<p>Existen tipos de datos no-primitivos, que son objetos, y que tienen su alternativa primitiva, entre estos tenemos el <code>String</code> (nótese la mayúscula en la <strong>S</strong>). Veamos un ejemplo de como un <code>String</code> puede ser un objeto</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> nombrePrimitivo = <span class="hljs-string">"Carlos"</span>;
<span class="hljs-keyword">const</span> nombreNoPrimitivo = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(<span class="hljs-string">"Fernando"</span>);
</code></pre>
<p>Intentando añadir propiedades a ambos objetos</p>
<pre><code class="lang-javascript">nombrePrimitivo.apellido = <span class="hljs-string">"Arias"</span>;
nombreNoPrimitivo.apellido = <span class="hljs-string">"Barrios"</span>;
</code></pre>
<p>Añadiendo logs</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(nombrePrimitivo); <span class="hljs-comment">// Salida: Carlos</span>
<span class="hljs-built_in">console</span>.log(nombrePrimitivo.apellido); <span class="hljs-comment">// Salida: undefined</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> nombrePrimitivo); <span class="hljs-comment">// Salida: string</span>

<span class="hljs-built_in">console</span>.log(nombreNoPrimitivo); <span class="hljs-comment">// Salida: String {'Fernando', apellido: 'Barrios**'}</span>
<span class="hljs-built_in">console</span>.log(nombreNoPrimitivo.apellido); <span class="hljs-comment">// Salida: 'Barrios'</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> nombreNoPrimitivo); <span class="hljs-comment">// Salida: object</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[¿Qué son los empty-statement en javascript? ¿Existen casos de uso?]]></title><description><![CDATA[Javascript tiene ciertas peculiaridades que en ciertos momentos resultan ser importantes, o al menos interesantes, de conocer. Puede que los empty-statement sean de esas peculiaridades de JavaScript que resultan no ser tan necesarias o al menos no co...]]></description><link>https://jfbarrios.com/que-son-los-empty-statement-en-javascript-existen-casos-de-uso</link><guid isPermaLink="true">https://jfbarrios.com/que-son-los-empty-statement-en-javascript-existen-casos-de-uso</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Sun, 27 Feb 2022 01:39:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/GUSPPE-NjH8/upload/v1645922635328/2pabjHzeW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Javascript tiene ciertas peculiaridades que en ciertos momentos resultan ser importantes, o al menos interesantes, de conocer. Puede que los <code>empty-statement</code> sean de esas peculiaridades de JavaScript que resultan no ser tan necesarias o al menos no con tantos casos de uso.</p>
<h2 id="heading-que-es-un-statement">¿Qué es un statement?</h2>
<p>una sentencia (statement) es una unidad sintáctica de un lenguaje de programación imperativo que expresa alguna acción a realizar. Podemos decir que son las unidades ejecutable más pequeña de un programa.</p>
<p>Si tiene una línea de código que dice <code>var x= 10; consola.log(x);</code> eso es una línea y 2 sentencias.</p>
<h2 id="heading-que-son-los-empty-statement-en-javascript">¿Qué son los empty-statement en javascript?</h2>
<p>Un <code>empty-statement</code> o sentencia vacía es usada para no proveer una sentencia, incluso si la sintaxis JavaScript esperase una. En pocas palabras un <code>empty-statement</code> es un <code>;</code> (punto y coma).</p>
<p>Una sentencia vacía no proporciona ninguna declaración aunque JavaScript la espere. La declaración no tiene ningún efecto y no realiza ninguna acción.</p>
<p>Un ejemplo típico sería crear un bucle for que no tenga cuerpo.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

<span class="hljs-comment">// Asignar el valor 0 a todos los elementos del array</span>
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; arr.length; arr[i++] = <span class="hljs-number">0</span>) <span class="hljs-comment">/* sentencia vacía */</span> ;

<span class="hljs-built_in">console</span>.log(arr);
<span class="hljs-comment">// [0, 0, 0]</span>
</code></pre>
<p>Siempre se recomienda añadir un comentario a nuestro código cuando estamos utilizando sentencias vacías de forma intencional.</p>
<p>Un ejemplo de un uso no intencional (Mozilla Doc):</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (condicion);  <span class="hljs-comment">// Esta condición no ejerce ningún control!</span>
   borrarTodo()  <span class="hljs-comment">// Por lo cual esta sentencia será ejecutada siempre!!!</span>
</code></pre>
<h2 id="heading-algunos-ejemplos-de-uso">Algunos ejemplos de uso</h2>
<h3 id="heading-asigna-a-b-el-valor-cero-si-a-no-es-cero">Asigna a 'b' el valor cero si 'a' no es cero.</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span>, b = <span class="hljs-number">1</span>;
<span class="hljs-keyword">if</span>((a == <span class="hljs-number">0</span>) || (b = <span class="hljs-number">0</span>));
<span class="hljs-built_in">console</span>.log(b); <span class="hljs-comment">// 0</span>
</code></pre>
<h3 id="heading-cadenas-de-if-else-para-excluir-ciertas-condiciones">Cadenas de <code>if-else</code>, para excluír ciertas condiciones</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> name = <span class="hljs-string">"Fernando"</span>;

<span class="hljs-keyword">if</span> (name === <span class="hljs-string">"Barrios"</span>)
    <span class="hljs-built_in">console</span>.log(name);
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (name === <span class="hljs-string">"Fernando"</span>)
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hola <span class="hljs-subst">${name}</span>`</span>); <span class="hljs-comment">// Hola Fernando</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (name === <span class="hljs-string">"Juan"</span>); <span class="hljs-comment">// No se realiza ninguna acción si el nombre pasado es "Juan"</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (name === <span class="hljs-string">"Carlos"</span>)
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Gusto en verte <span class="hljs-subst">${name}</span>`</span>);
<span class="hljs-keyword">else</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Adiós"</span>);
</code></pre>
<h3 id="heading-para-evitar-un-comportamiento-no-deseado-en-iifehttpsdevelopermozillaorgesdocsglossaryiife-en-algun-momento-querra-anteponerlo-con-una-declaracion-vacia">Para evitar un comportamiento no deseado en <a target="_blank" href="https://developer.mozilla.org/es/docs/Glossary/IIFE">IIFE</a>, en algún momento querrá anteponerlo con una declaración vacía</h3>
<pre><code class="lang-javascript">;(<span class="hljs-function">()=&gt;</span><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'hola'</span>))()
</code></pre>
<h3 id="heading-esperar-a-que-una-condicion-se-cumpla">Esperar a que una condición se cumpla</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">while</span> ( !condition );
<span class="hljs-comment">// haz lo que sucede una vez que se cumple tu condición</span>
</code></pre>
<h2 id="heading-referencias">Referencias:</h2>
<ol>
<li><a target="_blank" href="https://dev.to/bhagatparwinder/the-empty-statement-in-javascript-3lg7#:~:text=An%20empty%20statement%20provides%20no,loop%20that%20has%20no%20body.&amp;text=It%20is%20a%20good%20idea,on%20using%20an%20empty%20statement.">The Empty Statement</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/Empty">Empty Statement</a></li>
<li><a target="_blank" href="https://stackoverflow.com/questions/34840628/what-is-the-point-of-using-empty-statement-in-javascript">What is the point of using empty statement in JavaScript?</a></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Crear tu propio comando de git: git my-command]]></title><description><![CDATA[Introducción
Soy de las personas que siempre ando buscando "hacks" para simplificar mi trabajo y eliminar tareas repetitivas, si eres como yo, espero que este tutorial te ayude en tu día a día. 
Git Aliases
Antes de entrar en suelo de los git command...]]></description><link>https://jfbarrios.com/crear-tu-propio-comando-de-git</link><guid isPermaLink="true">https://jfbarrios.com/crear-tu-propio-comando-de-git</guid><category><![CDATA[Git]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Bash]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Thu, 24 Feb 2022 19:58:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645732605074/cpMb_As4M.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduccion">Introducción</h2>
<p>Soy de las personas que siempre ando buscando "hacks" para simplificar mi trabajo y eliminar tareas repetitivas, si eres como yo, espero que este tutorial te ayude en tu día a día. </p>
<h3 id="heading-git-aliases">Git Aliases</h3>
<p>Antes de entrar en suelo de los <code>git commands</code>, es importante que entendamos que la mayor parte de necesidades se pueden solucionar utilizando <code>git aliases</code> por ejemplo dentro de mi <code>.gitconfig</code> tengo el siguiente alias:</p>
<pre><code class="lang-bash">lg = <span class="hljs-built_in">log</span> --color --graph --pretty=format:<span class="hljs-string">'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset'</span> --abbrev-commit
</code></pre>
<p>Lo que me permite es generar una salida de parecida a esta:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645730493288/DDrGJ97cD.png" alt="image.png" /></p>
<h3 id="heading-git-commands">Git Commands</h3>
<p>Existen ciertas tareas que se tornan más complejas y que resulta ser mejor crear un comando en lugar de un alias.</p>
<p>La forma de trabajar de <code>git</code> es que cada vez que ejecutas <code>git commit</code> a su vez ejecuta un archivo binario o script llamado <code>git-commit</code>; si ejecutas <code>git branch</code> este a su vez ejecuta el archivo con nombre <code>git-branch</code>.</p>
<p><strong>¿Dónde están ubicados todos estos archivos?</strong></p>
<p>Si deseas visualizar donde se almacenan estos archivos debes de ejecutar en tu terminal:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> $(git --exec-path) &amp;&amp; ls
</code></pre>
<p>Obtendrás algo parecido a esto:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645730913257/8idbLg3Ca.png" alt="image.png" /></p>
<h2 id="heading-creando-nuestro-propio-comando">Creando nuestro propio comando</h2>
<p>Vamos a crear un comando que nos permita <code>renombrar</code> una branch local y remota. Es posible que exista una mejor forma de hacerlo, pero a manera didáctica usaremos este caso como ejemplo para construir nuestro script.</p>
<h3 id="heading-paso-1-crear-los-pasos-a-ejecutarse-en-el-script">Paso 1: Crear los pasos a ejecutarse en el script</h3>
<p>Los pasos que nuestro script deberá seguir, son:</p>
<ol>
<li>Crear una nueva branch a partir de la branch actual y que utilice el nuevo nombre.</li>
<li>Publicar la nueva branch en el remoto.</li>
<li>Eliminar la branch actual en el remoto.</li>
<li>Eliminar la branch actual en el local.</li>
</ol>
<h3 id="heading-paso-2-creando-el-archivo">Paso 2: Creando el archivo</h3>
<p>El nombre de nuestro archivo deberá tener la siguiente nomenclatura <code>git-nombre-de-mi-comando</code>, por lo que utilizaré <code>git-rename</code> para que pueda ejecutar <code>git rename branch_nueva</code>.</p>
<h3 id="heading-paso-3-reando-un-menu-de-ayuda-sobre-el-comando">Paso 3: reando un menú de ayuda sobre el comando.</h3>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/sh</span>
<span class="hljs-comment"># File: git-rename</span>

USAGE=<span class="hljs-string">'[help]'</span>
LONG_USAGE=<span class="hljs-string">'git rename help
    Muestra el mensaje de ayuda
git rename nombre_nuevo
    Elimina la branch actual y crea una nueva apartir de la misma en local y remoto.'</span>

OPTIONS_SPEC=
. git-sh-setup <span class="hljs-comment"># Documentación https://git-scm.com/docs/git-sh-setup</span>
</code></pre>
<p>El scriptlet <code>git sh-setup</code> está diseñado para ser obtenido (usando <code>.</code>) por otros scripts de shell para configurar algunas variables que apunten a los directorios normales de Git y algunas funciones auxiliares de shell.</p>
<h3 id="heading-paso-4-creando-la-funcion-a-invocar">Paso 4: Creando la función a invocar</h3>
<p>Crearemos la función <code>rename_branch</code> que hace lo siguiente:</p>
<ol>
<li>Crea una variable <code>currentBranch</code> que tiene como valor el nombre de la branch actual.</li>
<li>Imprime un mensaje de que renombrará la branch por el primer argumento que recibe la función</li>
<li><p>Ejecuta los pasos que creamos en el paso 1.</p>
<pre><code class="lang-bash"><span class="hljs-function"><span class="hljs-title">rename_branch</span></span> () {
 <span class="hljs-built_in">declare</span> currentBranch=$(git symbolic-ref --short HEAD);

 <span class="hljs-built_in">echo</span> <span class="hljs-string">"Renombrando branch <span class="hljs-variable">$currentBranch</span> por <span class="hljs-variable">$1</span>"</span>

 git checkout -b <span class="hljs-variable">$1</span> &amp;&amp; git push --set-upstream origin <span class="hljs-variable">$1</span> &amp;&amp; git push origin --delete <span class="hljs-variable">$currentBranch</span> &amp;&amp; git branch -D <span class="hljs-variable">$currentBranch</span>

 <span class="hljs-built_in">echo</span> <span class="hljs-variable">$1</span>;
}
</code></pre>
</li>
</ol>
<h3 id="heading-paso-5-mostrando-mensaje-de-ayuda-o-invocando-la-funcion">Paso 5: Mostrando mensaje de ayuda o invocando la función</h3>
<p>Cada vez que se ejecute este archivo, debemos de capturar el números de argumentos que hemos recibido, en caso no venga ninguno, mostraremos el mensaje de ayuda.</p>
<p>Si viene al menos un argumento, capturaremos el valor y revisaremos si es <code>help</code> para mostrar el mensaje de ayuda, caso contrario invocaremos la función de <code>rename_branch</code> con el valor.</p>
<pre><code class="lang-bash"><span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">$#</span>"</span> <span class="hljs-keyword">in</span>
0)
    usage ;;
*)
    cmd=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
      <span class="hljs-built_in">shift</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">$cmd</span>"</span> <span class="hljs-keyword">in</span>
      <span class="hljs-built_in">help</span>)
        git rename -h ;;
      *)
        rename_branch <span class="hljs-string">"<span class="hljs-variable">$cmd</span>"</span> ;;
    <span class="hljs-keyword">esac</span>
<span class="hljs-keyword">esac</span>
</code></pre>
<h3 id="heading-paso-6-guardando-el-archivo">Paso 6: Guardando el archivo</h3>
<p>Guarda el archivo en la ruta que obtuviste con <code>git --exec-path</code> y cambiale el permiso para que sea ejecutable con <code>chmod +x ./git-rename</code></p>
<h2 id="heading-script-final">Script final</h2>
<p>Este sería el script final:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/sh</span>
<span class="hljs-comment"># File: git-rename</span>

USAGE=<span class="hljs-string">'[help]'</span>
LONG_USAGE=<span class="hljs-string">'git rename help
    Muestra el mensaje de ayuda
git rename nombre_nuevo
    Elimina la branch actual y crea una nueva apartir de la misma en local y remoto.'</span>

OPTIONS_SPEC=
. git-sh-setup

<span class="hljs-function"><span class="hljs-title">rename_branch</span></span> () {
    <span class="hljs-built_in">declare</span> currentBranch=$(git symbolic-ref --short HEAD);

    <span class="hljs-built_in">echo</span> <span class="hljs-string">"Renombrando branch <span class="hljs-variable">$currentBranch</span> por <span class="hljs-variable">$1</span>"</span>

    git checkout -b <span class="hljs-variable">$1</span> &amp;&amp; git push --set-upstream origin <span class="hljs-variable">$1</span> &amp;&amp; git push origin --delete <span class="hljs-variable">$currentBranch</span> &amp;&amp; git branch -D <span class="hljs-variable">$currentBranch</span>

    <span class="hljs-built_in">echo</span> <span class="hljs-variable">$1</span>;
}

<span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">$#</span>"</span> <span class="hljs-keyword">in</span>
0)
    usage ;;
*)
    cmd=<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
      <span class="hljs-built_in">shift</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">$cmd</span>"</span> <span class="hljs-keyword">in</span>
      <span class="hljs-built_in">help</span>)
        git rename -h ;;
      *)
        rename_branch <span class="hljs-string">"<span class="hljs-variable">$cmd</span>"</span> ;;
    <span class="hljs-keyword">esac</span>
<span class="hljs-keyword">esac</span>
</code></pre>
<p>Espero que este pequeño tutorial te brinde las posibilidades de automatizar tu día a día.</p>
]]></content:encoded></item><item><title><![CDATA[Usa console.table en lugar de console.log]]></title><description><![CDATA[Una forma interesante de mostrar los resultados de un array o un objeto es utilizar console.table. Esta función toma un argumento obligatorio: data, que debe ser un array o un objeto, y un parámetro adicional: columns.
Colecciones de tipos primitivos...]]></description><link>https://jfbarrios.com/usa-consoletable-en-lugar-de-consolelog</link><guid isPermaLink="true">https://jfbarrios.com/usa-consoletable-en-lugar-de-consolelog</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[tips]]></category><category><![CDATA[logging]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Mon, 21 Feb 2022 19:58:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645475742436/m-tOX4dCp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Una forma interesante de mostrar los resultados de un array o un objeto es utilizar <code>console.table</code>. Esta función toma un argumento obligatorio: <code>data</code>, que debe ser un <code>array</code> o un <code>objeto</code>, y un parámetro adicional: <code>columns</code>.</p>
<h2 id="heading-colecciones-de-tipos-primitivos">Colecciones de tipos primitivos</h2>
<pre><code class="lang-javascript"><span class="hljs-comment">// Array de string</span>
<span class="hljs-built_in">console</span>.table([<span class="hljs-string">'Manzana'</span>, <span class="hljs-string">'Pera'</span>, <span class="hljs-string">'Melón'</span>]);
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645472655115/WDgKzSjm4.png" alt="image.png" /></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Objeto con propiedades de tipo strings</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Persona</span>(<span class="hljs-params">nombres, apellidos</span>) </span>{
  <span class="hljs-built_in">this</span>.nombres = nombres;
  <span class="hljs-built_in">this</span>.apellidos = apellidos;
}

<span class="hljs-keyword">var</span> yo = <span class="hljs-keyword">new</span> Persona(<span class="hljs-string">"Fernando"</span>, <span class="hljs-string">"Barrios"</span>);

<span class="hljs-built_in">console</span>.table(yo);
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645472681381/Q4nwYb5s3.png" alt="image.png" /></p>
<h2 id="heading-colecciones-de-tipos-compuestos">Colecciones de tipos compuestos</h2>
<p>Si <code>data</code> es un <code>array</code> y sus elementos son <code>array</code>, o bien cuando <code>data</code> sea un objeto y sus propiedades sean un <code>array</code> sus propiedades o elementos se enumerarán en la fila.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// un array de arrays</span>

<span class="hljs-keyword">var</span> personas = [[<span class="hljs-string">"Fernando"</span>, <span class="hljs-string">"Barrios"</span>], [<span class="hljs-string">"Juan"</span>, <span class="hljs-string">"Carlos"</span>], [<span class="hljs-string">"Carmen"</span>, <span class="hljs-string">"María"</span>]]
<span class="hljs-built_in">console</span>.table(personas);
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645472977487/dX1V6mO36.png" alt="image.png" /></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// un array de objetos</span>

<span class="hljs-built_in">console</span>.table([{
    <span class="hljs-attr">nombre</span>: <span class="hljs-string">"Fernando"</span>,
    <span class="hljs-attr">apellido</span>: <span class="hljs-string">"Barrios"</span>
}, {
    <span class="hljs-attr">nombre</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">apellido</span>: <span class="hljs-string">"Doe"</span>
}])
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645473295171/uvxmrnE5k.png" alt="image.png" /></p>
<h2 id="heading-restringiendo-las-columnas-mostradas">Restringiendo las columnas mostradas</h2>
<pre><code class="lang-javascript"><span class="hljs-comment">// un array de objetos, donde se mostrará solo la columna apellido</span>

<span class="hljs-built_in">console</span>.table([{
    <span class="hljs-attr">nombre</span>: <span class="hljs-string">"Fernando"</span>,
    <span class="hljs-attr">apellido</span>: <span class="hljs-string">"Barrios"</span>
}, {
    <span class="hljs-attr">nombre</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">apellido</span>: <span class="hljs-string">"Doe"</span>
}], [<span class="hljs-string">'apellido'</span>])
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645473387454/tID3Hq0Kv.png" alt="image.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Principios SOLID en JavaScript]]></title><description><![CDATA[SOLID es el acrónimo que introdujo Robert C. Martin a principios de los años 2000 que representan los cinco principios que debes de considerar en la programación orientada a objetos. Estos principios no son más que guías que puedes o no aplicar en el...]]></description><link>https://jfbarrios.com/principios-solid-en-javascript</link><guid isPermaLink="true">https://jfbarrios.com/principios-solid-en-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[solid]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Fri, 18 Feb 2022 04:07:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/5YtdzN7f7-c/upload/v1645156331512/a-D5bNPQx.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>SOLID es el acrónimo que <a target="_blank" href="https://es.wikipedia.org/wiki/SOLID">introdujo Robert C. Martin</a> a principios de los años 2000 que representan los cinco principios que debes de considerar en la programación orientada a objetos. Estos principios no son más que guías que puedes o no aplicar en el desarrollo de software, pero que te permiten crear sistemas extensibles, flexibles, legibles y con un código limpio (spoiler: en futuras entradas hablaremos sobre código limpio). Podemos concluir que los principios SOLID nos permiten alto grado de <strong>cohesión</strong> y bajo <strong>acoplamiento</strong>.</p>
<h2 id="heading-que-es-la-cohesion">¿Qué es la cohesión?</h2>
<p>La cohesión en términos de informática se refiere al grado en que diferentes elementos de un mismo sistema permanecen unidos generando un elemento mayor. Podríamos verlo como una clase que integra varios métodos y cada uno de estos métodos está relacionado entre sí, teniendo una “temática” común.</p>
<h2 id="heading-que-es-el-acoplamiento">¿Qué es el acoplamiento?</h2>
<p>El acoplamiento es el grado en que todos estos elementos se relacionan entre sí. Entre mayor sean las relaciones o dependencias mayor grado de acoplamiento tendremos.</p>
<h2 id="heading-como-aplicar-los-principios-solid-en-javascript">Cómo aplicar los principios SOLID en JavaScript</h2>
<p>Ya vimos un poco de teoría y ahora nos vamos a enfocar en la práctica. En esta parte de este artículo buscaremos cómo aplicar cada uno de los principios en éste maravilloso lenguaje.</p>
<p>Por cierto, si estás buscando como convertirte en un mejor desarrollador de software, te dejo <a target="_blank" href="https://laserants.com/6-cosas-que-puedes-hacer-para-convertirte-en-un-mejor-desarrollador-de-software/">esta guía que fue escrita en Laserants</a>.</p>
<h2 id="heading-los-cinco-principios-solid-son">Los cinco principios SOLID son:</h2>
<ul>
<li>S – Principio de responsabilidad única (Single responsibility principle)</li>
<li>O – Principio de abierto/cerrado (Open/Close principle)</li>
<li>L – Principio de sustitución de Liskov (Liskov substitution principle)</li>
<li>I – Principio de segregación de la interfaz (Interface segregation principle)</li>
<li>D - Principio de inversión de la dependencia (Dependency inversion principle)</li>
</ul>
<h3 id="heading-principio-de-responsabilidad-unica">Principio de Responsabilidad Única</h3>
<p>Nos dice que una <strong>clase o función</strong> debe centrarse en una única responsabilidad, que debe existir una única razón para cambiar; en resumen podemos decir que éste principio nos pide que todos los métodos o sub-funciones tengan alta cohesión.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auto</span> </span>{
  <span class="hljs-keyword">constructor</span>(marca, modelo) {
    <span class="hljs-built_in">this</span>.marca = marca;
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }

  obtenerMarca() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.marca;
  }

  obtenerModelo() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.modelo;
  }

  guardarMarca(marca) {
    <span class="hljs-built_in">this</span>.marca = marca;
  }

  guardarModelo(modelo) {
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }
}
</code></pre>
<p>En este ejemplo podemos ver como la clase Auto tiene métodos específicos para leer y escribir información, pero no hace nada adicional como guardar en una base de datos, llamar a otras funciones ajenas.</p>
<h3 id="heading-principio-de-abiertocerrado">Principio de Abierto/Cerrado</h3>
<p>Nos dice que debemos ser capaces de extender el comportamiento de una clase/función sin modificar.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductosEnAlacena</span> </span>{
  productos = [<span class="hljs-string">"Piña"</span>, <span class="hljs-string">"Manzanas"</span>, <span class="hljs-string">"Harina"</span>];

  existeProducto(producto) {
    <span class="hljs-comment">// indexOf nos devuelve la posición del producto en el array,</span>
    <span class="hljs-comment">// si la posición es -1 significa que no existe el producto</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.productos.indexOf(producto) !== <span class="hljs-number">-1</span>;
  }
}
</code></pre>
<p>Si quisiéramos a la clase <code>ProductosEnAlacena</code> añadirle la posibilidad de ingresar más productos entonces haríamos lo siguiente:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductosEnAlacena</span> </span>{
  productos = [<span class="hljs-string">"Piña"</span>, <span class="hljs-string">"Manzanas"</span>, <span class="hljs-string">"Harina"</span>];

  existeProducto(producto) {
    <span class="hljs-comment">// indexOf nos devuelve la posición del producto en el array,</span>
    <span class="hljs-comment">// si la posición es -1 significa que no existe el producto</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.productos.indexOf(producto) !== <span class="hljs-number">-1</span>;
  }

  agregarProducto(producto) {
    <span class="hljs-built_in">this</span>.productos.push(producto);
  }
}
</code></pre>
<p>Como se puede observar, le hemos hecho modificaciones a la clase, sin alterar la funcionalidad previa, cumpliendo así con el principio.</p>
<h3 id="heading-principio-de-sustitucion-de-liskov">Principio de sustitución de Liskov</h3>
<p>El principio nos indica que si estás usando una clase <code>Rectangulo</code> y luego creas otra clase llamada <code>Cuadrado</code> que extiende de <code>Rectangulo</code> entonces cualquier objeto creado a partir de la clase <code>Rectangulo</code> puede ser cambiado por <code>Cuadrado</code>, obligándonos así a que cualquier clase hija no altere el comportamiento de la clase padre.</p>
<p>Entonces tendríamos un rectángulo:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangulo</span> </span>{
  ancho;
  alto;

  establecerAncho(ancho) {
    <span class="hljs-built_in">this</span>.ancho = ancho;
  }

  establecerAlto(alto) {
    <span class="hljs-built_in">this</span>.alto = alto;
  }

  calcularArea() {
    <span class="hljs-keyword">return</span> ancho * alto;
  }
}
</code></pre>
<p>Y tenemos una prueba escrita en mocha para comprobar el área:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">"Validar área de un rectángulo "</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  it(<span class="hljs-string">"El área debe ser igual a alto * ancho "</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> rectangulo = <span class="hljs-keyword">new</span> Rectangulo();
    rectangulo.establecerAncho(<span class="hljs-number">8</span>);
    rectangulo.establecerAlto(<span class="hljs-number">2</span>);
    <span class="hljs-keyword">const</span> area = rectangulo.calcularArea();
    assert.equal(area, <span class="hljs-number">16</span>);
  });
});
</code></pre>
<p>Si ejecutamos la prueba nos encontramos que el área debe ser equivalente a 16, resultado de multiplicar ancho (8) por alto (2).</p>
<p>Ahora creamos una clase <code>Cuadrado</code> que extiende de <code>Rectangulo</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cuadrado</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Rectangulo</span> </span>{
  establecerAncho(ancho) {
    <span class="hljs-built_in">super</span>.establecerAncho(ancho);
    <span class="hljs-built_in">super</span>.establecerAlto(ancho);
  }

  establecerAlto(alto) {
    <span class="hljs-built_in">super</span>.establecerAncho(alto);
    <span class="hljs-built_in">super</span>.establecerAlto(alto);
  }
}
</code></pre>
<p>Para validar que no rompimos el funcionamiento del padre, correremos la prueba sobre un objeto creado con la clase <code>Cuadrado</code>. Al correr la prueba nos daremos cuenta que ha fallado, pues ahora un cuadrado escribe el ancho y alto como el mismo valor imposibilitando tener el área de un rectángulo con lados diferentes.</p>
<p>Hasta éste punto te estarás preguntando como solucionarlo, y creo que has de estar pensando en diferentes posibilidades. La primera y más sencilla puede ser abstraer la lógica a una clase superior quedando el código de la siguiente manera:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Paralelogramo</span> </span>{
  <span class="hljs-keyword">constructor</span>(ancho, alto) {
    <span class="hljs-built_in">this</span>.establecerAncho(ancho);
    <span class="hljs-built_in">this</span>.establecerAlto(alto);
  }

  establecerAncho(ancho) {
    <span class="hljs-built_in">this</span>.ancho = ancho;
  }

  establecerAlto(alto) {
    <span class="hljs-built_in">this</span>.alto = alto;
  }

  calcularArea() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.ancho * <span class="hljs-built_in">this</span>.alto;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangulo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Paralelogramo</span> </span>{
  <span class="hljs-keyword">constructor</span>(ancho, alto) {
    <span class="hljs-built_in">super</span>(ancho, alto);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cuadrado</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Paralelogramo</span> </span>{
  <span class="hljs-keyword">constructor</span>(lado) {
    <span class="hljs-built_in">super</span>(lado, lado);
  }
}
</code></pre>
<h3 id="heading-principio-de-segregacion-de-la-interfaz">Principio de segregación de la interfaz</h3>
<p>El principio nos indica que una clase debe de implementar únicamente las interfaces que necesita, es decir, que no necesite tener que implementar métodos que no utilice. El propósito de este principio es <strong>obligarnos a escribir interfaces pequeñas</strong> buscando aplicar el principio de cohesión en cada interfaz.</p>
<p>Imaginemos que tenemos un negocio de venta de computadoras de escritorio, sabemos que todas las computadoras deberían de extender de la clase Computadora y tendríamos algo como esto:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Computadora</span> </span>{
  marca;
  modelo;

  <span class="hljs-keyword">constructor</span>(marca, modelo) {
    <span class="hljs-built_in">this</span>.marca = marca;
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }

  obtenerMarca() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.marca;
  }

  obtenerModelo() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.modelo;
  }

  guardarMarca(marca) {
    <span class="hljs-built_in">this</span>.marca = marca;
  }

  guardarModelo(modelo) {
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ComputadoraDell</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Computadora</span> </span>{
   ...
}
</code></pre>
<p>En nuestro negocio todo va de maravilla y ahora queremos extender un poco más nuestro catalogo de productos, así que decidimos optar por empezar a vender computadoras portátiles. Un atributo útil de una portátil es el tamaño de la pantalla integrada, pero como bien sabemos esto solo esta presente en las portátiles y no computadoras de escritorio (generalizando), al inicio podemos pensar que una implementación podría ser:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Computadora</span> </span>{
  ...
  constructor() {
    ...
  }
  ...
  guardarTamanioPantalla(tamanio) {
    <span class="hljs-built_in">this</span>.tamanio = tamanio;
  } 
  obtenerTamanioPantalla() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.tamanio;
  }
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PortatilHP</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Computadora</span> </span>{
   ...
}
</code></pre>
<p>El problema que tenemos con esta implementación es que no todas las clases, por ejemplo la <code>EscritorioDell</code>, requieren los métodos para leer y escribir el tamaño de la pantalla integrada, entonces deberíamos de pensar en separar ambas lógicas en dos interfaces quedando nuestro código así:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Computadora</span> </span>{
  marca;
  modelo;

  <span class="hljs-keyword">constructor</span>(marca, modelo) {
    <span class="hljs-built_in">this</span>.marca = marca;
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }

  obtenerMarca() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.marca;
  }

  obtenerModelo() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.modelo;
  }

  guardarMarca(marca) {
    <span class="hljs-built_in">this</span>.marca = marca;
  }

  guardarModelo(modelo) {
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TamanioPantallaIntegrada</span> </span>{
  tamanio;
  <span class="hljs-keyword">constructor</span>(tamanio) {
    <span class="hljs-built_in">this</span>.tamanio = tamanio;
  }

  guardarTamanioPantalla(tamanio) {
    <span class="hljs-built_in">this</span>.tamanio = tamanio;
  }

  obtenerTamanioPantalla() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.tamanio;
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PortatilAsus</span> <span class="hljs-title">implements</span> &lt;<span class="hljs-title">TamanioPantallaIntegrada</span>, <span class="hljs-title">Computadora</span>&gt; </span>{
  ...
}
</code></pre>
<p>Todo suena perfecto, pero <strong>¿te has dado cuenta del problema?</strong>, y es que <strong>JavaScript solo soporta una clase padre</strong>, entonces la solución sería aplicar un mixin, este sería el código utilizando un mixin:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Computadora</span> </span>{
  marca;
  modelo;

  <span class="hljs-keyword">constructor</span>(marca, modelo) {
    <span class="hljs-built_in">this</span>.marca = marca;
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }

  obtenerMarca() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.marca;
  }

  obtenerModelo() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.modelo;
  }

  guardarMarca(marca) {
    <span class="hljs-built_in">this</span>.marca = marca;
  }

  guardarModelo(modelo) {
    <span class="hljs-built_in">this</span>.modelo = modelo;
  }
}

<span class="hljs-keyword">const</span> Portatil = <span class="hljs-function">(<span class="hljs-params">clasePadre</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">clasePadre</span> </span>{
      <span class="hljs-keyword">constructor</span>(marca, modelo){
        <span class="hljs-built_in">super</span>(marca, modelo);
      }

      guardarTamanioPantalla(tamanio) {
        <span class="hljs-built_in">this</span>.tamanio = tamanio;
      }

      obtenerTamanioPantalla() {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.tamanio;
      }

    }
  )
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PortatilAsus</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Portatil</span>(<span class="hljs-title">Computadora</span>) </span>{
  ...
}
</code></pre>
<h3 id="heading-principio-de-inversion-de-dependencia">Principio de inversión de dependencia</h3>
<p>En este principio se establecen que las dependencias deben de estar en las abstracciones y no en las concreciones, en otras palabras, nos piden que las clases nunca dependan de otras clases y que toda esta relación debe estar en una abstracción. Este principio tiene dos reglas:</p>
<ol>
<li>Los módulos de alto nivel no deben de depender de módulos de bajo nivel. Esta lógica debe de estar en una abstracción.</li>
<li>Las abstracciones no deben de depender de detalles. Los detalles deberían depender de abstracciones.</li>
</ol>
<p>Imagina que tenemos una clase que nos permite enviar un correo:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Correo</span> </span>{
  provider;

  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-comment">// Levantar una instancia de google mail, este código es con fin de demostración.</span>
    <span class="hljs-built_in">this</span>.provider = gmail.api.createService();
  }

  enviar(mensaje) {
    <span class="hljs-built_in">this</span>.provider.send(mensaje);
  }
}

<span class="hljs-keyword">var</span> correo = <span class="hljs-keyword">new</span> Correo();
correo.enviar(<span class="hljs-string">'hola!'</span>);
</code></pre>
<p>En este ejemplo se puede ver que se está rompiendo la regla, puesto que la clase correo depende del proveedor de servicio, ¿qué pasaría si después queremos usar Yahoo y no Gmail?</p>
<p>Para solucionar esto debemos eliminar esa dependencia y añadirla como una abstracción.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GmailProveedor</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-comment">// Levantar una instancia de google mail, este código es con fin de demostración.</span>
    <span class="hljs-built_in">this</span>.provider = gmail.api.createService();
  }
  enviar(mensaje) {
    <span class="hljs-built_in">this</span>.provider.sendAsText(mensaje);
  }
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Correo</span> </span>{
  <span class="hljs-keyword">constructor</span>(proveedor) {
    <span class="hljs-built_in">this</span>.proveedor = proveedor;
  }
  enviar(mensaje) {
    <span class="hljs-built_in">this</span>.proveedor.send(mensaje);
  }
}
<span class="hljs-keyword">var</span> gmail = <span class="hljs-keyword">new</span> GmailProveedor();
<span class="hljs-keyword">var</span> correo = <span class="hljs-keyword">new</span> Correo(gmail);
correo.enviar(<span class="hljs-string">'hola!'</span>);
</code></pre>
<p>De esta forma ya no nos importa el proveedor ni la forma en que implementa el envío de correos el proveedor, la clase de Correo solo se ocupa de una única cosa, pedirle al proveedor que envíe un correo.</p>
<p>Hasta acá hemos terminado con esta publicación sobre los <strong>principios SOLID en Javascript</strong>, agradecería que me dejes comentarios y sugerencias sobre que otros temas te interesaría que repasaramos.</p>
]]></content:encoded></item><item><title><![CDATA[Reemplazar Switch por Objetos literales en JavaScript]]></title><description><![CDATA[Probablemente más de algunos de ustedes habrán escuchado en repetidas ocaciones que suele ser mejor usar Object Literals en lugar de sentencias switch o inclusive if.
Las sentencias switch, son de las primeras cosas que aprendemos cuando entramos al ...]]></description><link>https://jfbarrios.com/usar-objetos-literales-en-lugar-de-sentencias-switch-en-javascript</link><guid isPermaLink="true">https://jfbarrios.com/usar-objetos-literales-en-lugar-de-sentencias-switch-en-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[tips]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Fernando Barrios]]></dc:creator><pubDate>Thu, 17 Feb 2022 18:28:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/oqStl2L5oxI/upload/v1645128275586/jaBEGHCSJ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Probablemente más de algunos de ustedes habrán escuchado en repetidas ocaciones que suele ser mejor usar <code>Object Literals</code> en lugar de sentencias <code>switch</code> o inclusive <code>if</code>.</p>
<p>Las sentencias switch, son de las primeras cosas que aprendemos cuando entramos al mundo de la programación, y no, no están obsoletas. Para muchos programadores JavaScript estamos constantemente trabajando con Objetos y muchos de nosotros empezamos a utilizarlos como un reemplazo a una sentencia switch.</p>
<h2 id="heading-que-es-una-sentencia-switch">¿Qué es una sentencia switch?</h2>
<p>Nos permite evaluar una expresión, haciendo coincidir el valor de la expresión con una cláusula de caso y ejecuta las declaraciones asociadas con ese caso, veamos un ejemplo:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">obtenerPrecio</span>(<span class="hljs-params">producto</span>) </span>{
  <span class="hljs-keyword">switch</span> (producto) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"Naranjas"</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-string">"Mangos"</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-number">2.5</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-string">"Papayas"</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;
    <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
  }
}

obtenerPrecio(<span class="hljs-string">"Papayas"</span>); <span class="hljs-comment">// Salida: 3</span>
</code></pre>
<p>Podemos observar que es similar a sentencias de tipo if-else, con la diferencia que evalúa un único valor.</p>
<h2 id="heading-que-pasa-si-olvido-un-break-o-return">¿Qué pasa si olvido un break o return?</h2>
<p>El inconveniente más común que nos encontramos, es la forma en la que maneja el flujo de control, por ejemplo si nos olvidamos de colocar el 'break' seguirá ejecutando las lineas siguientes de código aún cuando en nuestra lógica no deban de ser ejecutadas, por ende, estamos obligados a añadir estas pausas. En el siguiente ejemplo, si <code>expresión</code> se resuelve a "Platanos", el algoritmo compara el valor con el case "Platanos" y ejecuta la declaración asociada. Cuando se encuentra un <code>break</code>, el programa sale del condicional <code>switch</code> y ejecuta la declaración que lo procede. Si se omite el <code>break</code>, el case "Cerezas" también es ejecutado. Este código lo pueden encontrar <a target="_blank" href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/switch#usando_switch">acá</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">switch</span> (expr) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Naranjas'</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'El kilogramo de naranjas cuesta $0.59.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Manzanas'</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'El kilogramo de manzanas cuesta $0.32.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Platanos'</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'El kilogramo de platanos cuesta $0.48.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Cerezas'</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'El kilogramo de cerezas cuesta $3.00.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Mangos'</span>:
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Papayas'</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'El kilogramo de mangos y papayas cuesta $2.79.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">default</span>:
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Lo lamentamos, por el momento no disponemos de '</span> + expr + <span class="hljs-string">'.'</span>);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"¿Hay algo más que te quisiera consultar?"</span>);
</code></pre>
<h2 id="heading-por-que-reemplazarlo-por-objetos-literales">¿Por qué reemplazarlo por objetos literales?</h2>
<p>Como hemos dicho, en JavaScript estamos acostumbrados a utilizar objetos para casi todo, ya sea como constructores o como objetos literales. Nuestros modelos de datos, información o variables suelen ser objetos literales de los cuales extraemos valores de sus propiedades.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> productos = {
    <span class="hljs-string">"naranjas"</span>: <span class="hljs-number">2</span>,
    <span class="hljs-string">"mangos"</span>: <span class="hljs-number">2.5</span>,
    <span class="hljs-string">"papayas"</span>: <span class="hljs-number">3</span>,
    <span class="hljs-string">"default"</span>: <span class="hljs-number">0</span>
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">obtenerPrecio</span>(<span class="hljs-params">producto</span>) </span>{
  <span class="hljs-keyword">return</span> productos[producto.toLowerCase()] || productos[<span class="hljs-string">'default'</span>];
}

obtenerPrecio(<span class="hljs-string">"Papayas"</span>); <span class="hljs-comment">// Salida: 3</span>
</code></pre>
<p>Hemos logrado ahorrarnos algunas líneas de código, pero principalmente hemos conseguido mayor legibilidad y no tenemos que preocuparnos por escribir pausas en el código.</p>
]]></content:encoded></item></channel></rss>