<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Mario Menjívar - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Mario Menjívar - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 16 May 2026 19:16:31 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/mariomenjr/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Explicación de los grupos de usuarios en Linux: cómo agregar un nuevo grupo, agregar un nuevo miembro, y cambiar de grupo ]]>
                </title>
                <description>
                    <![CDATA[ > Linux permite a multiples usuarios tener acceso al sistema operativo a la vez. La configuración de permisos proteje a los usuarios de ellos mismos. Los usuarios pueden ser asignados a grupos para compartir privilegios, seguridad y acceso. El acceso de archivos y dispositivos puede ser restringido en base a ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/explicacion-de-los-grupos-de-usuarios-en-linux/</link>
                <guid isPermaLink="false">5fee3f078c7cd154bb9827fc</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Menjívar ]]>
                </dc:creator>
                <pubDate>Sun, 28 Feb 2021 05:38:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/01/christina-wocintechchat-com-faEfWCdOKIg-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>Linux permite a multiples usuarios tener acceso al sistema operativo a la vez. La configuración de permisos proteje a los usuarios de ellos mismos. Los usuarios pueden ser asignados a grupos para compartir privilegios, seguridad y acceso. El acceso de archivos y dispositivos puede ser restringido en base a usuarios específicos o grupos de usuarios.</blockquote><p>Los grupos se usan con frecuencia para permitir que ciertos usuarios modifiquen un archivo o directorio.</p><p>Los dos tipos de grupos principales son grupos primarios y grupos secundarios. El grupo primario de un usuario es el grupo por defecto con el que se asocia la cuenta, generalmente comparte el mismo nombre que el usuario. Los directorios y los archivos que el usuario crea tendrán asignados este grupo. Un grupo secundario es cualquier grupo adicional del que un usuario sea parte.</p><h2 id="creaci-n-de-grupos"><strong>Creación de grupos</strong></h2><p>Creemos dos grupos llamados "writers" y "editors". Usa el comando <code>groupadd</code> (es posible que necesites usar el comando <code>sudo</code> al inicio para tener el permiso adecuado para crear el grupo):</p><pre><code>groupadd writers
groupadd editors</code></pre><h2 id="creaci-n-de-usuarios"><strong>Creación de usuarios</strong></h2><p>Puede que ya tengas usuarios para agregar a tu grupo. Si no, aquí está la sintaxis básica para crear un usuario con el comando <code>useradd</code>:</p><p><code>useradd [options] username</code></p><p>Aquí está para crear un usuario llamado "quincy". El argumento <code>-m</code> le dice al comando que cree el directorio principal del usuario con el mismo nombre que el usuario. El argumento con su valor <code>-p p4ssw0rd</code> crea la contraseña "p4ssw0rd" para el usuario.</p><p><code>useradd -m quincy -p password</code></p><p>Los usuarios serán capaces de cambiar su contraseña con el comando <code>passwd</code>. Para ello, tendrán que ingresar su contraseña actual en ese momento y luego definir una nueva.</p><h2 id="agregar-un-usuario-a-un-grupo"><strong>Agregar un usuario a un grupo</strong></h2><p>Puedes usar el comando <code>usermod</code> para agregar un usuario a un grupo. Así es cómo agregaríamos el usuario "quincy" al grupo "writers". El argumento <code>-a</code> significa "añadir" (append) y el argumento <code>-G</code> agrega un grupo como un grupo secundario.</p><p><code>usermod -a -G writers quincy</code></p><p>Cuando un usuario es creado con el comando <code>adduser</code>, este es automáticamente asignado a un grupo primario con el mismo nombre que el usuario. En nuestro ejemplo, actualmente el usuario "quincy" es parte de un grupo primario "quincy" y de un grupo secundario "writers".</p><p>También puedes agregar un usuario a muchos grupos a la vez al separar por comas los nombres de los grupos, así <code>-G group1,group2,group3</code>.</p><p>El siguiente comando cambia el grupo primario del usuario "quincy" de "quincy" a "editors": </p><p><code>usermod -g editors quincy</code></p><h2 id="remover-un-usuario-de-un-grupo-secundario">Remover un usuario de un grupo secundario</h2><p>Para remover un usuario de un grupo secundario necesitas sobreescribir los grupos a los que actualmente este usuario pertenece, por una nueva lista de grupos dónde no esté el grupo que se quiere remover.</p><p>Primero, usa el comando <code>id</code> para verificar a cuáles grupos secundarios pertenece un usuario:</p><p><code>id -nG quincy</code></p><p>Digamos que este comando nos devuelve <code>editors writers</code>, esto indica que el usuario "quincy" es parte de los grupos "editors" y "writers". Si quieres remover al usuario del grupo "writers", usa el comando:</p><p><code>usermod -G editors quincy</code></p><p>Ese comando establece como grupo secundario del usuario "quincy" como "editors". Ya que el argumento <code>-a</code> no fue usado, los grupos previos fueron sobreescritos.</p><h2 id="conclusi-n">Conclusión</h2><p>Deberías ahora estar listo para manejar usuarios y grupos en Linux. El siguiente paso es determinar qué privilegios debería tener cada grupo.</p><p>Traducido del artículo de <strong><a href="https://www.freecodecamp.org/news/author/beau/">Beau Carnes</a></strong> - <strong><a href="https://www.freecodecamp.org/news/linux-user-groups-explained-how-to-add-a-new-group-a-new-group-member-and-change-groups/">Linux User Groups Explained: How to add a new group, a new group member, and change groups</a></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo escribir un buen mensaje de commit: Una guía práctica de Git ]]>
                </title>
                <description>
                    <![CDATA[ Para crear un historial de revisión útil, los equipos primero deberían ponerse de acuerdo en una convención para los mensajes de commit (mensajes de confirmación). Eso también aplica para proyectos personales. Recientemente pregunté en Hashnode [https://hashnode.com], "¿Cuál convención de mensaje usas en tus commits en el trabajo?" recibí muchas respuestas ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-escribir-un-buen-mensaje-de-commit/</link>
                <guid isPermaLink="false">5fd99dae8c7cd154bb9778b2</guid>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Menjívar ]]>
                </dc:creator>
                <pubDate>Thu, 21 Jan 2021 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2020/12/yancy-min-842ofHC6MaI-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Para crear un historial de revisión útil, los equipos primero deberían ponerse de acuerdo en una convención para los mensajes de <em>commit </em>(mensajes de confirmación). Eso también aplica para proyectos personales.</p><p>Recientemente pregunté en <a href="https://hashnode.com">Hashnode</a>, <strong>"¿Cuál convención de mensaje usas en tus <em>commits </em>en el trabajo?"</strong> recibí muchas respuestas de usuarios quejándose de las convenciones que usan en el trabajo y proyectos personales.</p><figure class="kg-card kg-embed-card"><iframe id="twitter-widget-0" scrolling="no" allowtransparency="true" allowfullscreen="true" class="" style="position: static; visibility: visible; width: 550px; height: 581px; display: block; flex-grow: 1;" title="Twitter Tweet" src="https://platform.twitter.com/embed/index.html?creatorScreenName=iambolajiayo&amp;dnt=false&amp;embedId=twitter-widget-0&amp;frame=false&amp;hideCard=false&amp;hideThread=false&amp;id=1198903055372165120&amp;lang=en&amp;origin=https%3A%2F%2Fwww.freecodecamp.org%2Fnews%2Fwriting-good-commit-messages-a-practical-guide%2F&amp;siteScreenName=freecodecamp&amp;theme=light&amp;widgetsVersion=ed20a2b%3A1601588405575&amp;width=550px" data-tweet-id="1198903055372165120" frameborder="0" loading="lazy"></iframe></figure><p>En este artículo explicaré cómo escribir un buen mensaje de <em>commit</em> y por qué tú deberías darle importancia.</p><h3 id="ps-este-art-culo-fue-publicado-primero-aqu-"><em>PS: Este artículo fue publicado primero <a href="https://bolajiayodeji.com/writing-good-commit-messages-a-practical-guide-ck3izs56t00sed0s11z515m1j">aquí</a>.</em></h3><p></p><h2 id="introducci-n-al-control-de-versiones-con-git">Introducción al control de versiones con Git</h2><p>El software de control de versiones es una parte esencial de las prácticas de desarrollo de software modernas.</p><p>Por mucho, <a href="https://git-scm.com/">Git</a> es el controlador de versiones más ampliamente utilizado en el mundo. Es un proyecto de código abierto, distribuido y activamente en desarrollo. Fue originalmente desarrollado en 2005 por <a href="https://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a>, el famoso creador del kernel Linux.</p><h2 id="-qu-es-un-commit">¿Qué es un <em>commit</em>?</h2><p>El comando <strong><em>commit</em></strong> se usa para confirmar los cambios en el área de preparación y guardarlos en el repositorio local en Git. Sin embargo, antes de guardar algún cambio, tienes que decirle a Git cuáles cambios quieres incluir de los muchísimos que puedes haber hecho. Una excelente manera de hacerlo es agregar un mensaje en el <em><strong>commit</strong></em> para identificar tus cambios.</p><h3 id="opciones-de-comando-commit">Opciones de comando <em>commit</em></h3><ul><li><strong>-m</strong></li></ul><p>Esta opción establece el mensaje del <em>commit</em>.</p><pre><code class="language-bash">git add static/admin/config.yml
git commit -m "Configurar múltiples roles para netlify-cms git gateway"
</code></pre><ul><li><strong>-a </strong>ó<strong> --all</strong></li></ul><p>Esta opción confirma todos los archivos en el área de trabajo (esos nuevos, con modificaciones, o incluso eliminados) automáticamente..</p><pre><code class="language-bash">git commit -a -m "Agregar un nuevo rol para netlify-cms git gateway"
</code></pre><ul><li><strong>--amend</strong></li></ul><p>Esta opción reescribe el último <em>commit </em>con cualquier cambio que esté en el área de preparación o un nuevo mensaje, y solo debería ser incluido en <em>commits</em> que no han sido aún sincronizados con el repositorio remoto.</p><pre><code class="language-bash">git add .
git commit --amend -m "Actualizar roles para netlify-cms git gateway"
</code></pre><h2 id="-por-qu-deber-a-escribir-un-buen-mensaje-de-commit">¿Por qué debería escribir un buen mensaje de <em>commit</em>?</h2><p>Puede que digas: "Es solo un proyecto personal". Sí, puede que estés trabajando solo ahora, pero, ¿Qué pasa cuando trabajas con un equipo o contribuyes al código abierto?</p><p>Un mensaje de <em>commit </em>bien elaborado es la mejor manera de comunicar el contexto del cambio realizado a otros desarrolladores trabajando en el proyecto y también al futuro tú.</p><p>¿Haz alguna vez intentando ejecutar el comando <code>git log</code> en uno de tus proyectos viejos para ver los mensajes de commit "raros" que has usado desde su creación? Quizá sea difícil entender por qué hiciste algunos cambios en el pasado y es probable que desees haber leído este artículo antes.</p><p>Los mensajes de <em>commit </em>pueden comunicar adecuadamente el porqué un cambio fue hecho y de este modo entenderlo fácilmente. Haciendo más eficiente la colaboración y el desarrollo.</p><h2 id="c-mo-escribir-mensajes-de-commit-con-git">Cómo escribir mensajes de <em>commit</em> con Git</h2><p>Hasta hoy, solamente usaba <code>git commit -m "Arregle X para permitir que Y use Z"</code> en mis proyectos personales especificando solo un título sin ninguna descripción extra. Esto es perfecto para parches pequeños y claros de código como, <code>git commit -m "Corregi error tipográfico en README.md"</code> pero en casos donde hay cambios más extensos necesitamos agregar más detalles.</p><h3 id="m-todo-editor">Método editor</h3><p>Ejecuta <code>git commit</code> sin un mensaje u opción y se abrirá tu editor de texto predeterminado para escribir el mensaje de <em>commit</em>.</p><p>Para configurar tu editor "predeterminado":</p><pre><code>git config --global core.editor nano
</code></pre><p>Esto configurará Git para usar nano como editor predeterminado. Reemplaza "nano" con "emacs", "vim" o cualquiera de tu preferencia.</p><p>En el editor que se abrió, usa la primera línea para el título (corta descripción), deja una línea en blanco y todo lo de más es para la descripción extendida (cuerpo del mensaje).</p><pre><code class="language-bash">&lt;Resumir los cambio(s) en alrededor de 50 caracteres o menos&gt;

&lt;Descripción explicativa más detallada del cambio envuelto en aproximadamente 72 caracteres&gt;
</code></pre><h3 id="m-todo-de-l-nea-de-comando">Método de línea de comando</h3><pre><code>git commit -m "Sujeto" -m "Descripción..."
</code></pre><p>El primer argumento <code>-m</code> es para el título (corta descripción), y el siguiente es para la descripción extendida (cuerpo del mensaje).</p><h2 id="c-mo-escribir-buenos-mensajes-de-commit">Cómo escribir buenos mensajes de <em>commit</em></h2><p>Existen muchas convenciones que son usadas por diferentes equipos y desarrolladores para escribir bien mensajes de <em>commit</em>. Aquí solo mostraré algunas reglas generales y consejos para escribir buenos mensajes de <em>commit </em>– puedes escoger cuál de estas reglas quieres seguir. Y si trabajas para una compañía o contribuyes al código abierto, tienes que aceptar y adaptarte a su convención.</p><p>Por consistencia, puedes usar una convención para el trabajo y otra para proyectos personales. Cuando cambies de trabajo, puede que la convención sea diferente en el nuevo lugar.</p><p>Esta es una gran plantilla de un buen mensaje de <em>commit </em>escrito originalmente por <a href="https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html">Tim Pope:</a></p><pre><code class="language-bash">Aprovechar, Resumen breve (50 caracteres o menos)

Texto explicativo más detallado, si es necesario. Envuélvalo a unos 72 personajes más o menos. En algunos contextos, la primera línea se trata como asunto de un correo electrónico y el resto del texto como cuerpo. El espacio en blanco línea que separa el resumen del cuerpo es fundamental (a menos que omita todo el cuerpo); herramientas como rebase pueden confundirse si ejecuta el dos juntos.


Escriba su mensaje de confirmación en imperativo: "Corregir error" y no "Corregido error" o "Corrige error". Esta convención coincide con los mensajes de confirmación generados mediante comandos como git merge y git revert.

Los párrafos adicionales vienen después de las líneas en blanco.

- Las viñetas también están bien

- Normalmente se utiliza un guión o asterisco para la viñeta, seguido de un espacio único, con líneas en blanco en el medio, pero las convenciones varían aquí

- Usar una sangría colgante

Si utiliza un rastreador de problemas, agregue una referencia a ellos en la parte inferior, como tal:

Soluciona: #123
</code></pre><p>¿Se ve bien, no? Así es cómo tú puedes hacer el tuyo genial también:</p><ol><li>Especifica el tipo de <em>commit</em>:<br>	feat: La nueva característica que agregas a una aplicación en particular<br>	fix: Un parche para un error<br>	style: Características o actualizaciones relacionadas con estilos<br>	refactor: Refactorizar una sección específica de la base de código<br>	test: Todo lo relacionado con pruebas<br>	docs: Todo lo relacionado con documentación<br>	chore: Mantenimiento de código regular.</li><li>Separa el título del cuerpo del mensaje con una línea en blanco.</li><li>Tu mensaje de <em>commit</em> no debería contener ningún mensaje de espacios en blanco.</li><li>Quita signos de puntuación innecesarios.</li><li>No termines el título con un punto.</li><li>Usa mayúsculas al inicio del título y por cada párrafo del cuerpo del mensaje.</li><li>Usa el modo imperativo en el título.</li><li>Usa el cuerpo del mensaje para explicar cuáles cambios has hecho y por qué los hiciste.</li><li>No asumas que las personas que revisará el código entiende cuál era el problema original, asegúrate de agregar la información necesaria.</li><li>No piense que tu código se explica solo.</li><li>Sigue la convención del mensaje de <em>commit</em> definida por tu equipo.</li></ol><h2 id="conclusi-n">Conclusión</h2><p>La parte más importante de un mensaje de <em>commit</em> es que sea claro y entendible. A final de cuentas, escribir buenos mensajes de <em>commit</em> demuestra que tan buen colaborador eres. Los beneficios de escribir un buen mensaje de <em>commit </em>no se limitan a tu equipo, de hecho, se expanden a ti y tus futuros colaboradores.</p><p>Traducido del artículo de <strong><a href="https://www.freecodecamp.org/news/author/bolajiayodeji/">Bolaji Ayodeji</a></strong> - <strong><a href="https://www.freecodecamp.org/news/writing-good-commit-messages-a-practical-guide/">How to Write Good Commit Messages: A Practical Git Guide</a></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Debounce JavaScript – Cómo hacer que tu JS espere ]]>
                </title>
                <description>
                    <![CDATA[ > Las funciones de rebote (debounce) no se ejecutan al momento de su invocación. En lugar de eso, su ejecución es retrasada por un periodo predeterminado de tiempo. Si la misma función es invocada de nuevo, la ejecución previa es cancelada y el tiempo de espera se reinicia. Aquí hay ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/curso-debounce-javascript-como-hacer-que-tu-js-espere/</link>
                <guid isPermaLink="false">5fd422468c7cd154bb973a64</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Menjívar ]]>
                </dc:creator>
                <pubDate>Sun, 20 Dec 2020 17:20:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2020/12/samuel-elias-nadler--JzHSIzNYnU-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>Las funciones de rebote (<em><strong>debounce</strong></em>) no se ejecutan al momento de su invocación. En lugar de eso, su ejecución es retrasada por un periodo predeterminado de tiempo. Si la misma función es invocada de nuevo, la ejecución previa es cancelada y el tiempo de espera se reinicia.</blockquote><p>Aquí hay un corto vídeo dónde se muestra cómo hacer una función de rebote (en inglés):</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.25%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/NfYIiKRZTaU?feature=oembed" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" name="fitvid0" frameborder="0" width="256" height="144"></iframe>
          </div>
        </div>
      </figure><p>Y aquí está el código fuente que se muestra en el vídeo:</p><figure class="kg-card kg-embed-card"><iframe id="cp_embed_LYNPYmb" src="https://codepen.io/adeelibr/embed/preview/LYNPYmb?height=300&amp;slug-hash=LYNPYmb&amp;default-tabs=js,result&amp;host=https://codepen.io" title="Debounce Button onClick Example" scrolling="no" allowtransparency="true" class="cp_embed_iframe" style="width: 100%; overflow: hidden;" height="300" frameborder="0" loading="lazy"></iframe></figure><p>Ahora veamos el código con más detalles.</p><p>Asume que tienes un botón definido de la siguiente manera:</p><pre><code class="language-html">&lt;button id="myBtn"&gt;Click me&lt;/button&gt;</code></pre><p>Y en tu archivo JavaScript tienes algo parecido a esto:</p><pre><code class="language-js">document.getElementById('myBtn').addEventListener('click', () =&gt; {
  console.log('clicked');
})</code></pre><p>Cada vez que hagas clic en el botón, verás el mensaje "click" en tu consola.</p><p>Agreguemos ahora una función de rebote a nuestro manejador de evento <code>click</code>:</p><pre><code class="language-js">document.getElementById('myBtn').addEventListener('click', debounce(() =&gt; {
  console.log('click');
}, 2000))</code></pre><p>La función de rebote recibe dos párametros: <code>callback</code> y <code>wait</code>. El primero recibe la función que deseas ejecutar después de un periodo de tiempo, mientras que el segundo recibe el tiempo a esperar antes de ejecutar la función <code>callback</code>.</p><p>En el ejemplo de arriba, nuestra función <code>callback</code> simplemente es una función que ejecuta un <code>console.log('click');</code> y <code>wait</code> representa <code>2000 milisegundos</code> de espera.</p><p>Dado este escenario, definamos <code>debounce</code>:</p><pre><code class="language-js">function debounce(callback, wait) {
  let timerId;
  return (...args) =&gt; {
    clearTimeout(timerId);
    timerId = setTimeout(() =&gt; {
      callback(...args);
    }, wait);
  };
}</code></pre><p>La función <code>debounce</code> recibe dos parámetros: el <code>callback</code> (la función que queremos ejecutar luego de un periodo predeterminado) y el periodo de espera <code>wait</code> (después del cuál <code>callback</code> será ejecutado).</p><p>Dentro de la función <code>debounce</code>, simplemente retornamos otra función, así:</p><pre><code class="language-js">let timerId;
return (...args) =&gt; {
  clearTimeout(timerId);
  timerId = setTimeout(() =&gt; {
    callback(...args);
  }, wait);
};</code></pre><p>El próposito de esta función es invocar a la función <code>callback</code> después de cierto período de tiempo. Si durante el periodo de espera la misma función es ejecutada nuevamente, la ejecución previa es cancelada y el temporizador es reiniciado para empezar de nuevo.</p><p>¡Eso es todo! Todo lo que necesitas saber sobre qué es una función de debounce.</p><p>Aquí hay un video extra que habla sobre closures<em>,</em> ya que en este ejemplo usé un <code>closure</code> dentro de mi función <code>debounce</code>.</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.25%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/-Q7oXxxw0-c?feature=oembed" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" name="fitvid1" frameborder="0" width="256" height="144"></iframe>
          </div>
        </div>
      </figure><p>Avísame en <a href="https://twitter.com/adeelibr">Twitter </a>si pudiste encontrar el uso de <em>closure </em>dentro de la función <em>debounce</em>.</p><p>¡Feliz programación, a todos!<br><br>Traducido del artículo de <a href="https://www.freecodecamp.org/news/author/adeel/"><strong>Adeel Imran</strong></a><strong> -</strong> <strong><a href="https://www.freecodecamp.org/news/debounce-javascript-tutorial-how-to-make-your-js-wait-up/">Debounce JavaScript – How to Make your JS Wait Up</a></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Porqué deberías saber sobre Closures en JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ > Entender a la perfección de closures es un paso importante para convertirse en un desarrollador JavaScript. Hay una razón por la qué puede ser difícil entender los closures: por lo general, se enseña al revés. Puede que te hayan enseñado qué es un closure, pero es posible que no ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/porque-deberias-saber-sobre-javascript-closures/</link>
                <guid isPermaLink="false">5fd44b1c8c7cd154bb973d82</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Menjívar ]]>
                </dc:creator>
                <pubDate>Wed, 16 Dec 2020 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2020/12/Why-JS-Closures-Matter-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>Entender a la perfección de closures es un paso importante para convertirse en un desarrollador JavaScript.</blockquote><p>Hay una razón por la qué puede ser difícil entender los <em>closures</em>:<em> </em>por lo general, se enseña al revés. Puede que te hayan enseñado qué es un <em>closure</em>, pero es posible que no hayas entendido el porqué son útiles para el desarrollador promedio, o dentro de tu propio código.</p><p><strong>Entonces, ¿Por qué los <em>closures</em> importan en nuestro código JavaScript del día a día?</strong></p><p>En lugar de ver a los <em>closures</em> como un tema a memorizar para algún tipo de examen, veamos que pasos nos pueden llevar a ver un <em>closure</em> en primer lugar. Una vez veamos lo qué son, descubriremos porqué los <em>closures</em> valen la pena en tu código JavaScript.</p><h2 id="-haz-visto-un-closure-en-la-vida-real">¿Haz visto un <em>closure </em>en la vida real?</h2><p>Dígamos que estamos haciendo un clon del sitio de <em>blogging </em>Medium y queremos que cada usuario sea capaz de dar <em>me gusta</em> a diferentes posts.</p><p>Cada vez que un usuario haga click en el botón <em>me gusta</em>, su valor será incrementado por cada vez.</p><p>Piensa en el botón <em>aplaudir</em> de Medium:</p><figure class="kg-card kg-image-card"><img src="https://raw.githubusercontent.com/kikobeats/react-clap-button/HEAD/demo.gif" class="kg-image" alt="https://raw.githubusercontent.com/kikobeats/react-clap-button/HEAD/demo.gif" width="288" height="272" loading="lazy"></figure><p>La función <code>handleLikePost</code> manejará el incremento del contador, cada vez que se le de clic al botón, y la variable <code>likeCount</code> mantendrá el número de <em>me gusta </em>registrados:</p><pre><code class="language-js">// global scope
let likeCount = 0;

function handleLikePost() {
  // function scope
  likeCount = likeCount + 1;
}

handleLikePost();
console.log("like count:", likeCount); // like count: 1
</code></pre><p>Cuando un usuario haga clic en <em>me gusta</em> en un <em>post</em>, llamaremos a la función <code>handleLikePost</code> y esto incrementará nuestra variable <code>likeCount</code> en 1.</p><p>Esto funciona porque sabemos que esa función puede acceder a las variables fuera de sí mismas.</p><p>En otras palabras, <strong>las funciones pueden acceder cualquier variable definida en cualquier ámbito (<em>scope</em>) superior</strong>.</p><p>Sin embargo, hay un problema con este código. Ya que <code>likeCount</code> está en el ámbito global, y no en alguna función, <code>likeCount</code> es una variable global. Las variables globales pueden ser usadas (y actualizadas) por cualquier otra pieza de código o función en nuestra aplicación.</p><p>Por ejemplo, ¿Qué pasa si, erróneamente, después de nuestra función fijamos nuestra variable <code>likeCount</code> a cero?</p><pre><code class="language-js">let likeCount = 0;

function handleLikePost() {
  likeCount = likeCount + 1;
}

handleLikePost();
likeCount = 0;
console.log("like count:", likeCount); // like count: 0
</code></pre><p>Naturalmente, <code>likeCount</code> será siempre cero.</p><p>Cuando únicamente una función necesita una pieza de datos, ese dato solo necesita existir locamente, esto es, dentro de esa función.</p><p>Ahora traigamos <code>likeCount</code> dentro de nuestra función:</p><pre><code class="language-js">function handleLikePost() {
  // likeCount moved from global scope to function scope
  let likeCount = 0;
  likeCount = likeCount + 1;
}
</code></pre><p>Fíjate que hay una manera más corta de escribir la línea donde incrementamos <code>likeCount</code>. En lugar de decir que <code>likeCount</code> es igual al valor actual (en ese momento) de <code>likeCount</code> y agregar 1, podemos simplemente usar el operador +=, así:</p><pre><code class="language-Js">function handleLikePost() {
  let likeCount = 0;
  likeCount += 1;
}</code></pre><p>Y para que obtengamos el mismo resultado en consola, debemos también traernos nuestro <code>console.log</code> dentro de la función.</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  likeCount += 1;
  console.log("like count:", likeCount);
}

handleLikePost(); // like count: 1
</code></pre><p>Ahora vemos lo mismo que antes.</p><p>Ahora los usuarios deberían ser capaces de darle me gusta a un post las veces que ellos quieran, llamemos a la función <code>handleLikePost</code> unas cuantas veces más:</p><pre><code class="language-js">handleLikePost(); // like count: 1
handleLikePost(); // like count: 1
handleLikePost(); // like count: 1
</code></pre><p>Sin embargo, cuando ejecutamos este código, hay un problema.</p><p>Esperaríamos ver a la variable <code>likeCount</code> seguir incrementando, pero solo vemos un 1 cada vez. ¿Por qué pasa esto?</p><p>Detente un momento, mira nuestro código e intenta explicar porqué nuestra variable <code>likeCount</code> no se está incrementado cómo antes.</p><p>Veamos al código de la función <code>handleLikePost</code>:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  likeCount += 1;
  console.log("like count:", likeCount);
}
</code></pre><p>Cada vez que lo usamos, estamos recreando la variable <code>likeCount</code>, la cual es inicializada a cero.</p><p>¡No hay duda del porqué no podemos mantener la cuenta entre cada llamada a la función! La variable es constantemente inicializada a cero, luego se incrementa en 1, y después la función finaliza su ejecución.</p><p>Estamos atorados. Nuestra variable necesita vivir dentro de la función <code>handleLikePost</code>, pero no podemos mantener la cuenta.</p><p>Necesitamos algo que nos permita preservar o recordar el valor de la variable <code>likeCount</code> entre las llamadas a la función.</p><p>Qué tal si probamos algo que puede parecer un poco extraño a primera vista: qué tal si intentamos poner una función dentro de nuestra función:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  likeCount += 1;
  function() {

  }
}

handleLikePost();
</code></pre><p>Vamos a nombrar esta función <code>addLike</code>. ¿La razón? Porque ahora será responsable de incrementa la variable <code>likeCount</code>.</p><p>En la mayoría de casos, nuestra nueva función no necesitaría un nombre. Podría ser anónima. La estamos nombrando con el próposito de referinos a ella más fácilmente en nuestra explicación.</p><p>La función <code>addLike</code> ahora será responsable de incrementar nuestra variable <code>likeCount</code>, entonces moveremos la línea donde incrementamos la variable en 1 dentro de esta función interna.</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  function addLike() {
    likeCount += 1;
  }
}
</code></pre><p>¿Qué pasa si llamamos a la función <code>addLike</code> dentro de la función <code>handleLikePost</code>?</p><p>Lo qué pasará es que la función <code>addLike</code> incrementará la variable <code>likeCount</code>, pero aún así la variable <code>likeCount</code> será destruida. Así que, otra vez, perdemos la cuenta y nuestro resultado es cero.</p><p>Pero si en lugar de llamar a la función <code>addLike</code> dentro de su función padre, ¿Qué pasaría si la llamamos por fuera? Esto puede parecer aún más extraño. ¿Y cómo haríamos eso?</p><p>A este punto, sabemos que las funciones retornan valores. Por ejemplo, podríamos retornar el valor de la variable <code>likeCount</code> al final de la función <code>handleLikePost</code> para pasarlo a otras partes de nuestro programa:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  function addLike() {
    likeCount += 1;
  }
  addLike();
  return likeCount;
}
</code></pre><p>Pero en lugar de hacer eso, retornemos la variable <code>likeCount</code> dentro de la función <code>addLike</code> y luego retornemos a la función <code>addLike</code> misma:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  return function addLike() {
    likeCount += 1;
    return likeCount;
  };
  // addLike();
}

handleLikePost();
</code></pre><p>Esto puede verse bizarro, pero es permitido en JavaScript. Podemos tratar a las funciones como variables. Esto significa que una función puede ser retornada por otra función. Al retornar la función interna, podemos llamarla desde afuera de su función padre.</p><p>¿Pero cómo hacemos eso? Piensa en esto por un minuto e intenta averiguarlo por tu cuenta...</p><p>Primero, para ver mejor lo qué está pasando, vamos a imprimir la llamada a la función <code>handleLikePost</code> con un <code>console.log</code>, asi: <code>console.log(handleLikePost())</code>. Mira que pasa cuando lo ejecutamos:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  return function addLike() {
    likeCount += 1;
    return likeCount;
  };
}

console.log(handleLikePost()); // ƒ addLike()
</code></pre><p>Como era de esperarse, vemos a la función <code>addLike</code>. ¿Por qué? Porque la estamos retornado después de todo.</p><p>Para llamarla, ¿Podríamos solo recibirla en otra variable? Como acabamos de decir, las funciones pueden ser tratadas como cualquier otra variable en JavaScript. Si podemos retornar una función desde otra, podemos recibirla en una variable también. Recibamosla en una variable con nombre <code>like</code>:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  return function addLike() {
    likeCount += 1;
    return likeCount;
  };
}

const like = handleLikePost();
</code></pre><p>Y finalmente, llamemos <code>like</code>. Hagámoslo unas cuantas veces e imprimamos cada resultado con un <code>console.log</code>:</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  return function addLike() {
    likeCount += 1;
    return likeCount;
  };
}

const like = handleLikePost();

console.log(like()); // 1
console.log(like()); // 2
console.log(like()); // 3
</code></pre><p>¡Nuestra variable<code>likeCount</code> finalmente mantiene el conteo! Cada vez que nosotros llamamos a la función <code>like</code>, la variable <code>likeCount</code> es incrementada a partir de su valor previo.</p><p>¿Pero qué fue lo que paso aquí? Bien, averiguamos cómo llamar a la función <code>addLike</code> desde fuera del ámbito en el cuál fue declarada. Hicimos esto al retornar la función interna desde la función padre y, de esta manera, preservamos el acceso al ámbito de la función padre, la recibimos en la variable <code>like</code>, y al final, la ejecutamos.</p><h2 id="-c-mo-funciona-un-closure-l-nea-por-l-nea">¿Cómo funciona un closure, línea por línea?</h2><p>Sí, esa fue nuestra implementación, claro, ¿Pero cómo hicimos para preservar el valor de la variable <code>likeCount</code> entre cada llamada a la función?</p><pre><code class="language-js">function handleLikePost() {
  let likeCount = 0;
  return function addLike() {
    likeCount += 1;
    return likeCount;
  };
}

const like = handleLikePost();

console.log(like()); // 1
</code></pre><ol><li>Cuando la función padre <code>handleLikePost</code> es ejecutada, crea una instancia de la función interna <code>addLike</code>; esa función tiene <em>acceso directo</em> a la variable <code>likeCount</code>, la cuál está un ámbito más arriba.</li><li>Llamamos a la función <code>addLike</code> desde afuera del ámbito en el cuál fue declarada. Hicimos eso al retornar la función interna desde la función padre, así preservamos una referencia a su ámbito, la recibimos en la variables <code>like</code>, y la ejecutamos.</li><li>Cuando la función <code>like</code> finaliza su ejecución, normalmente, todas sus variables serían removidas de la memoria por el <em>garbage collector</em> (esto es un proceso automático que el compilador de JavaScript hace). Esperaríamos que cada valor de <code>likeCount</code> se elimine cuando la función termina, pero no pasa esto.</li></ol><p>¿Cuál es la razón? El <em>closure</em>.</p><p><strong>Ya que las instancias de la función interna aún viven (la función que recibimos en la variable <code>like</code>), el <em>closure</em> aún preserva el valor y el acceso a la variable <code>countLike</code>.</strong></p><p>Es normal pensar que declarar una función dentro de otra es como declarar una función en el ámbito global, pero no.</p><p><em>Es por esto que los <strong>closures </strong>dan a las funciones súper poderes</em>, porque es una propiedad especial que no está presente en en ninguna otra parte del lenguaje.</p><h2 id="la-vida-til-de-una-variable">La vida útil de una variable</h2><p>Para apreciar mejor a los <em>closures</em>, tenemos que entender cómo JavaScript trata a las variables que son creadas. Puedes haberte preguntado qué le pasa a las variables cuando cierro una página web o abro otra página dentro de la aplicación. ¿Cuánto viven las variables?</p><p>Las variables globales viven hasta que el programa es descartado, por ejemplo cuando cierras la ventana. Viven lo que viva la ejecución del programa.</p><p>Sin embargo, las variables locales tienen vidas cortas. Son creadas cuando una función es invocada, y eliminadas cuando la función termina su ejecución.</p><p>Así que antes, cuando la variable <code>likeCount</code> era solo una variables local, solo vivia mientras la función corría. La variable <code>likeCount</code> era creada al inicio de la ejecución y destruida al final.</p><h2 id="los-closures-no-son-capturas-instant-neas-mantienen-a-las-variable-locales-vivas">Los <em>closures</em> no son <em>capturas instantáneas</em>: mantienen a las variable locales vivas</h2><p>A veces se dice que los <em>closures</em> en JavaScript son similares a capturas instantáneas, una foto del programa en cierto periodo de tiempo. Esta es una idea equivocada que podemos disipar agregando otra característica a la funcionalidad de nuestro botón <em>me gusta</em>.</p><p>Dígamos que en raras ocaciones, queremos permitir a los usuarios que al hacer doble clic en el botón este incremente el valor de la variable <code>likeCount</code> por 2 en lugar de por 1.</p><p>¿Cómo agregamos esta característica?</p><p>Otra forma de pasar valores a una función es a través de argumentos, los cuales operan justo como variables locales.</p><p>Vamos a pasar un argumento nombrado <em>step</em> a la función, el cuál nos permitirá proveer un valor dinámico e intercambiable para incrementar nuestro contador en lugar de un valor fijo 1.</p><pre><code class="language-js">function handleLikePost(step) {
  let likeCount = 0;
  return function addLike() {
    likeCount += step;
    // likeCount += 1;
    return likeCount;
  };
}
</code></pre><p>Ahora, intentemos hacer una función especial que nos permitirá hacer doble clic a nuestros <em>posts</em>, <code>doubleLike</code>. Pasaremos un 2 como valor al argumento <code>step</code> y luego intentaremos llama a nuestras dos funciones, <code>like</code> and <code>doubleLike</code>:</p><pre><code class="language-js">function handleLikePost(step) {
  let likeCount = 0;
  return function addLike() {
    likeCount += step;
    return likeCount;
  };
}

const like = handleLikePost(1);
const doubleLike = handleLikePost(2);

like(); // 1
like(); // 2

doubleLike(); // 2 (the count is still being preserved!)
doubleLike(); // 4
</code></pre><p>Vemos que el valor de la variable <code>likeCount</code> se mantiene también para la función <code>doubleLike</code>.</p><p>¿Qué está pasando aquí?</p><p>Cada instancia de la función interna <code>addLike</code> preserva el acceso a las variables <code>likeCount</code> and <code>step</code> del ámbito de su función padre <code>handleLikePost</code>. La variable <code>step</code> se mantiene viva, y su valor es actualizado por cada invocación a la función interna. Ya qué el acceso al ámbito (el <em>closure</em>) es sobre las variables y no solo una instántanea de sus valores, estas actualizaciones son preservadas entre cada llamada a la función.</p><p>Entonces, ¿Todo lo que este código nos muestra es el hecho de que podemos pasar valores dinámicos para cambiar el resultado de nuestra función? No, no es todo. ¡Nos muestra qué las variables locales aún están vivas! Los <em>closures</em> mantienen a las variables locales vivas aún cuando estas debieron ser destruidas tiempo atrás.</p><p>En otras palabras, los <em>closures </em>no son estáticos y fijos, como una captura instantánea de los valores de las variables en cierto periodo del tiempo, sino que mantienen a las variables locales vivas y proveen acceso a ellas. Como resultado, podemos usar <em>closures</em> para observar o hacer actualizaciones a estas variables a lo largo del tiempo.</p><h2 id="-qu-es-exactamente-un-closure">¿Qué es exactamente un <em>closure</em>?</h2><p>Ya que viste porque los <em>closures</em> son útiles, hay dos condiciones para que exista un <em>closure</em>:</p><ol><li>Los <em>closures</em> son una propiedad exclusiva de las funciones.</li><li>Para crear un <em>closure</em>, primero debes ejecutar una función en un ámbito diferente a ese en el cuál se definió.</li></ol><h2 id="-por-qu-deber-amos-saber-de-closures">¿Por qué deberíamos saber de <em>closures</em>?</h2><p>Respondamos a la pregunta original que nos dimos a la tarea de responder. Basado en todo lo que has visto, detente un momento e intenta responderla tu mismo. ¿Por qué nos deberían importan los closures siendo desarrolladores JavaScript?</p><p>Los <em>closures</em> son importantes para ti y tu código porque nos permiten <strong>recordar </strong>valores, lo cuál es una muy poderosa y única característica en el lenguaje que solo las funciones poseen.</p><p>Lo vimos justo en este ejemplo. Después de todo, ¿Qué uso tiene una variable contador que no recuerda el número de <em>me gusta</em>? Te encontraras con eso frecuentemente en tu carrera al trabajar con JavaScript. Necesita mantener el valor de una variable pero a la vez separada del resto de variables. ¿Qué usas? Una función. ¿Por qué? Para mantener un valor a través del tiempo en un <em>closure</em>.</p><p>Y con eso, estas un paso adelante de otros desarrolladores.</p><h3 id="-quieres-convertirte-en-un-maestro-en-javascript-nete-al-js-bootcamp-2020-en-ingl-s-">¿Quieres convertirte en un maestro en JavaScript? Únete al JS Bootcamp 2020? (en inglés)</h3><figure class="kg-card kg-image-card"><img src="https://dev-to-uploads.s3.amazonaws.com/i/dzbyqgz7b03jf0b5l226.png" class="kg-image" alt="Join the 2020 JS Bootcamp" width="800" height="451" loading="lazy"></figure><p>Follow + Say Hi! ? <a href="http://twitter.com/intent/follow?source=followbutton&amp;variant=1.0&amp;screen_name=codeartistryio">Twitter</a> • <a href="https://instagram.com/codeartistry.io">Instagram</a> • <a href="https://codeartistry.io/">codeartistry.io</a></p><p>Traducido del artículo de <strong><a href="https://www.freecodecamp.org/news/author/reed/">Reed Barger</a></strong> - <strong><a href="https://www.freecodecamp.org/news/javascript-closures/">Why You Should Know JavaScript Closures</a></strong></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
