<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juan Miguel Rodriguez Ceron</title>
    <description>The latest articles on DEV Community by Juan Miguel Rodriguez Ceron (@juanmirod).</description>
    <link>https://dev.to/juanmirod</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F31838%2F91718722-cb17-44d1-86c1-ef2eb4950fe9.png</url>
      <title>DEV Community: Juan Miguel Rodriguez Ceron</title>
      <link>https://dev.to/juanmirod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juanmirod"/>
    <language>en</language>
    <item>
      <title>Using the Socratic method for mentoring</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Wed, 28 Jun 2023 21:04:47 +0000</pubDate>
      <link>https://dev.to/juanmirod/using-the-socratic-method-for-mentoring-l9l</link>
      <guid>https://dev.to/juanmirod/using-the-socratic-method-for-mentoring-l9l</guid>
      <description>&lt;p&gt;Using the Socratic method in the workplace can be a powerful tool for mentoring junior coworkers, guiding team meetings, and encouraging critical thinking and problem-solving skills.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h2jidTil--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/e/eb/Marcello_Bacciarelli_-_Alcibiades_Being_Taught_by_Socrates%252C_1776-77_crop.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2jidTil--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://upload.wikimedia.org/wikipedia/commons/e/eb/Marcello_Bacciarelli_-_Alcibiades_Being_Taught_by_Socrates%252C_1776-77_crop.jpg" alt="Alcibiades Being Taught by Socrates, 1776-77" width="720" height="638"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://commons.wikimedia.org/wiki/File:Marcello_Bacciarelli_-_Alcibiades_Being_Taught_by_Socrates,_1776-77_crop.jpg"&gt;Marcello Bacciarelli&lt;/a&gt;, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons







&lt;p&gt;I specially like when a coworker or team lead challenges my opinion with &lt;strong&gt;the right question&lt;/strong&gt;, it makes me think about possible solutions instead of feeling attacked or contradicted. This is why I am trying to learn how to do it and apply it myself when I have the opportunity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: The Socratic method is a very general term to describe the different techniques that Socrates used for teaching, encouraging critical thinking and discussion. In this post we will use it describe an approach about leading and mentoring at work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Socratic method involves asking open-ended questions that encourage coworkers to think deeply and critically&lt;/strong&gt; about the topic at hand, rather than simply telling them what to do. By giving them space to think and explore their own ideas, you'll be helping them become more confident and independent workers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Socratic questioning effectively
&lt;/h2&gt;

&lt;p&gt;When using the Socratic method, it's important to &lt;strong&gt;actively listen to your coworker's responses and ask follow-up questions to clarify their thinking&lt;/strong&gt;. This will help you understand their thought process and guide them towards a deeper understanding of the topic. Additionally, it's important to demonstrate that you're actively listening and engaged in the conversation by maintaining eye contact, using nonverbal cues, summarizing key points, and avoiding interrupting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Ask open-ended questions that encourage deep and critical thinking&lt;/li&gt;
&lt;li&gt;Actively listen to coworker's responses and ask follow-up questions&lt;/li&gt;
&lt;li&gt;Demonstrate active listening and engagement through nonverbal cues and summarizing key points&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Example 1: Pairing
&lt;/h2&gt;

&lt;p&gt;As any other method or technique, knowing the theory is not enough, practicing is key to know which is the right question and when to do a new question or when to wait and give space to the other person. For example, this are some questions you could use while pairing or reviewing code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's your understanding of the problem we're trying to solve here?&lt;/li&gt;
&lt;li&gt;How would you approach this problem if you were working on it alone?&lt;/li&gt;
&lt;li&gt;What are some potential solutions you've considered so far?&lt;/li&gt;
&lt;li&gt;What are the pros and cons of each solution?&lt;/li&gt;
&lt;li&gt;How would you test your solution to make sure it works as expected?&lt;/li&gt;
&lt;li&gt;Are there any edge cases or potential issues we should consider?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to use them when you are pairing or discussing a topic with a coworker or friend and observe how they react, if you surprised them or they feel that their opinion is important. Observe also yourself, asking this questions when you think that you know the right answer is difficult. Were you able to be patient while your mentee was trying to find the right words? Did you look calm and encouraging? Were you listening actively? &lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2: In team meetings
&lt;/h2&gt;

&lt;p&gt;In team meetings, it's important to encourage participation from all team members by creating a supportive and inclusive environment. Acknowledging the contributions of different team members and using visual aids to participate (like boards or post-its or any of the multiple virtual tools that we have for meetings) can help to create that collaborative environment.&lt;/p&gt;

&lt;p&gt;So, for example, if you have a board where every member of the team has to add an idea or a concern (maybe anonymously, depending on the topic) and then you read them aloud and comment each of them with the team, each team member will feel that they have been listened and they had the opportunity to express themselves.&lt;/p&gt;

&lt;p&gt;As a senior developer, it's important to participate in team meetings and contribute your expertise without dominating the conversation or imposing your point of view. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asking questions, providing context, sharing examples, encouraging collaboration, being neutral, and listening actively&lt;/strong&gt; are all ways to participate without giving a direct opinion.&lt;/p&gt;

&lt;p&gt;So, if you are one of the seniors members of the team, maybe you should try to lead some meetings using these practices, or simply offer yourself to take notes and lead the meeting from there. The person taking notes can summarize aloud what it has been said and remember any commitment or follow up actions that have been discussed.&lt;/p&gt;

&lt;p&gt;Key points to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encourage participation from all team members&lt;/li&gt;
&lt;li&gt;Listen actively and ask follow-up questions&lt;/li&gt;
&lt;li&gt;Summarize key points and ask for feedback&lt;/li&gt;
&lt;li&gt;Avoid dominating the conversation and encourage collaboration&lt;/li&gt;
&lt;li&gt;Keep an open mind and remain neutral&lt;/li&gt;
&lt;li&gt;Acknowledge contributions&lt;/li&gt;
&lt;li&gt;Use visual aids to encourage participation&lt;/li&gt;
&lt;li&gt;Follow up individually if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using the Socratic method in the workplace can be a powerful tool for mentoring junior coworkers and guiding team meetings. You can help your team members become more confident and independent workers, and encourage the generation of new ideas and solutions as a team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn more!
&lt;/h3&gt;

&lt;p&gt;Some links to keep learning about the topic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Socratic_questioning"&gt;Socratic questioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hbr.org/2018/05/the-surprising-power-of-questions"&gt;Asking good questions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LinkedIn Learning has many videos and courses about active listening that can be great to learn by example, f.e. &lt;a href="https://www.linkedin.com/learning-login/share?account=216505570&amp;amp;forceAccount=false&amp;amp;redirect=https%3A%2F%2Fwww.linkedin.com%2Flearning%2Fcentered-communication-get-better-results-from-your-conversations%2Factive-listening%3Ftrk%3Dshare_video_url%26shareId%3DpbPDhe03R1q3Env1ZFsyww%253D%253D"&gt;this video about active listening&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This post was created and edited by me with help of AI and Google, I was learning about the topic and I thought that it may be useful to share a summary on the topic.&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>meetings</category>
      <category>learninpublic</category>
    </item>
    <item>
      <title>Developing with ChatGPT</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Mon, 24 Apr 2023 08:55:24 +0000</pubDate>
      <link>https://dev.to/juanmirod/developing-with-chatgpt-2jfm</link>
      <guid>https://dev.to/juanmirod/developing-with-chatgpt-2jfm</guid>
      <description>&lt;p&gt;Are you curious about the possibilities of ChatGPT and how it can be used in your own projects? With the recent exciting advancements in language models and generative AI, there's never been a better time to dive in and start experimenting. In this blog post, I'll be sharing my own journey of developing a personal assistant using ChatGPT - from the challenges I faced to the solutions I discovered along the way.&lt;/p&gt;

&lt;p&gt;As someone who has been following the exciting advancements in language models, generative AIs, and artificial intelligence, I couldn't wait to dive into the world of ChatGPT. It represented a paradigm shift in the way we think about natural language processing.&lt;/p&gt;

&lt;p&gt;For me, it was a clear sign that I needed to start taking learning about these topics more seriously, so I embarked on a &lt;a href="https://github.com/juanmirod/chatgpt_cli"&gt;personal project&lt;/a&gt; to create my own personal assistant using ChatGPT. I wanted to experiment and learn at my own pace, without the constraints of a directed course.&lt;/p&gt;

&lt;p&gt;My ultimate goal was to develop an assistant that really knew me - one that would remember our previous conversations and run on my own personal computer. Even if I never quite achieve this lofty ambition, I knew that working on this project would be a fantastic way to immerse myself in the topic.&lt;/p&gt;

&lt;p&gt;To make things even more challenging, I decided to use Python - a language I wasn't particularly proficient in - and to always rely on ChatGPT instead of turning to Google or external documentation. This created a project that was not only challenging and exciting, but also incredibly meta. By using ChatGPT to develop tools that will ultimately replace it with my own personalized version.&lt;/p&gt;

&lt;p&gt;For now the experience is great. I develop new functionality very quickly, ChatGPT unlocks me very often and keeps me much more in the flow than having to read documentation or search Google and in general the feeling of speed and satisfaction is great. I also believe that this is because I'm using ChatGPT in the ideal scenario: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A new and small project, a command-line app, so adding functionality is very easy, you don't need frameworks or components or big architectures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a language I don't master, ChatGPT is very useful to solve doubts, and the domain itself is ChatGPT's specialty. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python is a language especially suitable for LLMs because it has less syntax and is dynamic. Properties that make it ideal for humans and LLMs because right now it's the closest thing we have to programming in natural language. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without all these factors, the usefulness of ChatGPT starts to degrade for me. In fact, at work I use it much less often, it's just harder to explain what I want than to do it myself. But that's why I think we will all end up with our own personal or company assistant who knows the ins and outs of our projects and can help us with more context... &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zO7FBwbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdgjzlr75eczxhmj4vb5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zO7FBwbN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdgjzlr75eczxhmj4vb5.jpg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But let's get to the point, I'm going to list some examples of how I've used ChatGPT in this project and when I can I'll link to specific conversations about that topic that I had with ChatGPT. These are some things I've done with ChatGPT to work, not just to explore what it knows, learn or try to play or entertain myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Readme&lt;/strong&gt;: The first version of the Readme was written by ChatGPT, I edited it and have been expanding and improving it since then.&lt;a href="https://gist.github.com/juanmirod/fce0104af6714c7527fce54639706407"&gt;Read the conversation here&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;: I asked ChatGPT for a dockerfile because to be honest I don't know the syntax by heart and I always end up copy-pasting. At first it gave me a completely functional dockerfile and the command to execute the assistant from the dockerfile. Then I edited it a bit to remove some things I didn't need and change the order of the commands a bit to better use docker's cache.&lt;a href="https://gist.github.com/juanmirod/7be1a16f017ea8798754870d1bcd7ffa"&gt;Conversation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TTS&lt;/strong&gt;: The assistant has a text-to-speech option so you can listen to its responses, although by default I have it disabled (it's faster to read and the code doesn't make sense to listen to). The first version was again its own, then I tried several voices and libraries, and in the end I settled on one that wasn't the one ChatGPT suggested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upload conversation to a gist&lt;/strong&gt;. I also asked ChatGPT for the upload file, then I put the code into a function to use it from the app instead of as a script.&lt;a href="https://gist.github.com/juanmirod/8b6044b0071bdcc5cb0bbcf933b7a576"&gt;Conversation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retrieve a conversation parsing the markdown file&lt;/strong&gt;. This is not integrated yet, but I've already played with ChatGPT and have the initial code that should make it possible.&lt;a href="https://gist.github.com/juanmirod/4f0e8687b4620831afb1446aed027b0c"&gt;Conversation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactors&lt;/strong&gt;. I've done several refactors where I've given it a big function and asked it to split it into smaller functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tests&lt;/strong&gt;. The first tests of the ChatGPT class were done by ChatGPT, and the ones for the actions module were done with copilot's help. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general ChatGPT has helped me throughout the process. from outlining solutions, consulting how libraries work, writing tests... The pattern is similar every time, and that's why I think it's especially useful if you don't master the language, because if you do, you'll take the same time or less to write it yourself. But if you don't know the available libraries and modules, asking ChatGPT how it would do it saves a lot of time in trial and error and research and reading documentation.&lt;/p&gt;

&lt;p&gt;Besides, for me this process is usually a rabbit hole: I start looking for a library to do X and there are 10's, and now I have to see which ones are more popular and why, and I want to see a little how they work... and when I realize it's been 2 hours and I haven't done anything. With ChatGPT all that process is much more immediate and fluid, even if I end up using another library or heavily editing or discarding its first solution. It keeps me more in the flow and more focused on the problem than all those websites full of ads and cookie popups, videos and other distractions. &lt;/p&gt;

&lt;p&gt;I'm sure I'm only scratching the surface here. LLMs seem to have a lot of potential at various levels, and little by little we'll be integrating them into IDEs and user interfaces, but even in this rudimentary form and without knowing very well what I'm doing I think I gain a lot of productivity and the development process is much less frustrating.&lt;/p&gt;

&lt;p&gt;Thanks a lot for reading, if you got this far please tell me what you think in the comments. Have you used ChatGPT for programming? Do you have a specific setup or workflow? I would love to know about it!&lt;/p&gt;




&lt;p&gt;This blog post was translated by ChatGPT from the original Spanish one which you can read &lt;a href="http://juanmirod.github.io/2023/04/16/trabajando-con-chat-gpt.html"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>python</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>Introducción a Node.js</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Mon, 16 Jul 2018 22:06:13 +0000</pubDate>
      <link>https://dev.to/juanmirod/introduccin-a-nodejs-npj</link>
      <guid>https://dev.to/juanmirod/introduccin-a-nodejs-npj</guid>
      <description>&lt;p&gt;(Este post fue publicado inicialmente en mi blog, pásate para ver más contenido sobre desarrollo, javascript y tecnología: &lt;a href="http://juanmirod.github.io/"&gt;Por amor al código&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt; es un entorno de ejecución de JavaScript que utiliza el motor V8 de Google. La historia de JavaScript y de Node.js es curiosa porque casi parece que todo surgió por accidente. JavaScript es conocido por haber sido &lt;a href="http://juanmirod.github.io/public/javascript10days.pdf"&gt;diseñado en 10 días por Bredan Eich&lt;/a&gt; y por sus &lt;a href="https://www.destroyallsoftware.com/talks/wat"&gt;inconsistencias&lt;/a&gt;, pero aun así, se ha convertido en el el lenguaje de facto de la web. La imposición tecnológica de los navegadores, unido a la bajísima curva de aprendizaje han hecho de JavaScript el lenguaje con más crecimiento de los últimos tiempos. Herramientas como jQuery, Mootools y Backbone, Lodash, Angular, React... Han ido evolucionando la arquitectura de un lenguaje dinámico en principio carente de estructura. JS es en la actualidad uno de los lenguajes más utilizados y de mayor crecimiento. Con lo que era inevitable que los desarrolladores de JavaScript quisieran usar el lenguaje fuera de los navegadores. Como dice la Ley de Atwood:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any application that can be written in JavaScript, will eventually be written in JavaScript &lt;a href="https://blog.codinghorror.com/the-principle-of-least-power/"&gt;ver más&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Antes de Node.js hubo varios intentos de establecer un entorno de ejecución para JavaScript fuera de los navegadores. Los programadores querían sacar JavaScript del corsé del navegador, querían poder hacer aplicaciones, modificar ficheros y acceder al hardware. Una historia muy entretenida sobre los inicios de Node.js y npm la cuenta el propio Issac Z. Schlueter (creador de npm) &lt;a href="http://blog.izs.me/post/157295170418/my-first-npm-publish"&gt;en su blog&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; Node.JS y npm se convirtieron en el entorno de ejecución de JavaScript en el servidor. Ahora podemos utilizar el mismo lenguaje para desarrollar en el servidor y en el cliente en el caso del desarrollo web, aunque también hay gente usando Node para ioT, para robots, para herramientas de línea de comandos, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación y el REPL
&lt;/h2&gt;

&lt;p&gt;Para instalar Node.js en Windows o en Mac, basta con ir a la página principal y descargar el instalador. Si usas Ubuntu, solo necesitamos un par de comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si usas otra distribución de Linux, &lt;a href="https://nodejs.org/en/download/package-manager/#installing-node-js-via-package-manager"&gt;mira aquí&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Una vez instalado podemos comprobar que la versión es la correcta (actualmente la versión LTS es la 6.x) escribiendo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
node -v


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ejecutar el intérprete de Node, el REPL, simplemente escribimos el comando &lt;code&gt;node&lt;/code&gt; y el terminal pasará a ser una consola de JavaScript en la que podremos ejecutar nuestro código.&lt;/p&gt;

&lt;p&gt;El REPL (siglas del inglés Read Eval Print Loop) es una consola que ejecuta cada expresión en JavaScript que le demos y devuelve el resultado de la expresión inmediatamente. Por ejemplo si escribimos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; 2 + 2
4

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;4&lt;/code&gt; es el resultado de la expresión &lt;code&gt;2 + 2&lt;/code&gt;, otro ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; console.log('Hola Mundo')
'Hola Mundo'
undefined

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;'Hola mundo' es la salida que produce &lt;code&gt;console.log('Hola Mundo')&lt;/code&gt; y &lt;code&gt;undefined&lt;/code&gt; es lo que devuelve la función. También podemos definir funciones y variables &lt;code&gt;globales&lt;/code&gt; que podremos usar a continuación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; var factorial  = function(x) {
...   if ( x &amp;lt;= 1 ) return x
...   return x * factorial(x-1)
... } 
undefined
&amp;gt; factorial(4)
24

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En las versiones actuales de Node.js tenemos soporte de prácticamente la totalidad de la especificación de ES2015, con lo que podríamos escribir la función de arriba de otra forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; const factorial  = x =&amp;gt; ( x &amp;lt;= 1 ) ? x : x * factorial(x-1) 
undefined
&amp;gt; factorial(4)
24

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El REPL es muy útil para probar pequeñas funciones y expresiones, yo cada vez lo utilizo más a menudo y los ejemplos de este blog suelen estar escritos de forma que sean fáciles de probar en el REPL. La ventaja de tener una respuesta inmediata a una duda de código es invaluable y normalmente no nos damos cuenta de eso hasta que lo probamos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Módulos y npm
&lt;/h2&gt;

&lt;p&gt;Node no es solo el REPL, también podemos ejecutar ficheros. Solo tenemos que crear un fichero con el código javascript que queramos ejecutar y pasárselo al comando &lt;code&gt;node&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
echo 'console.log("Hello Node")' &amp;gt; hello.js
node hello.js
// Hello Node

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada fichero JavaScript es un módulo para Node.js y si queremos usar alguna función definida dentro del fichero primero tendremos que exportarla. Por ejemplo creemos el fichero &lt;code&gt;factorial.js&lt;/code&gt; con el siguiente contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const factorial = x =&amp;gt; ( x &amp;lt;= 1 ) ? x : x * factorial(x-1)

module.exports = factorial


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si ejecutamos ese fichero veremos que no pasa nada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
node factorial.js 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuestro módulo no hace nada a parte de definir una función y exportarla, pero desde el propio REPL o desde otro fichero Node.js podremos importar esta función y utilizarla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; const factorial = require('./factorial.js')
&amp;gt; factorial(5)
120

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Mola eh? Ya tenemos un mecanismo para escribir código, encapsularlo en módulos y ejecutarlo. Esta es la base del desarrollo en Node, tan sencillo como eso. &lt;/p&gt;

&lt;p&gt;Node trae una serie de módulos básicos que podemos utilizar a modo de &lt;a href="https://nodejs.org/dist/latest-v6.x/docs/api/"&gt;librería estandard&lt;/a&gt; Pero uno de los puntos fuertes de Node.js es el haberse mantenido flexible gracias a tener una librería estandar muy pequeña.&lt;/p&gt;

&lt;p&gt;Ese es también el punto fuerte de npm. &lt;a href="https://www.npmjs.com/"&gt;npm&lt;/a&gt; es un repositorio centraliazdo de módulos para Node.js En la comunidad de Node.js y npm la filosofía también es la de módulos pequeños que hagan una sola cosa, parecido a lo que ocurre con los comandos de Unix. Esto hace el lenguaje más fácil de componer, reordenar y modificar y tiene un gran potencial. Ahora mismo npm es el repositorio con mayor número de módulos de código abierto de todos los lenguajes y su número sigue creciendo a mayor velocidad que todos los demás.&lt;/p&gt;

&lt;p&gt;npm se instala en nuestro sistema junto con Node.js y podemos usarlo para instalar cualquier paquete de forma global o local a nuestro proyecto. Un proyecto es simplemente una carpeta donde hemos ejecutado &lt;code&gt;npm init&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
mkdir hello
cd hello
npm init

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al ejecutar este comando el programa nos hará algunas preguntas sobre el proyecto y creará un fichero &lt;code&gt;package.json&lt;/code&gt; con la configuración mínima. Si solo queremos probar a instalar algunos paquetes podemos ejecutar &lt;code&gt;npm init -y&lt;/code&gt; para crear este fichero y npm usará la configuración mínima por defecto y el nombre de la carpeta como nombre del proyecto.&lt;/p&gt;

&lt;p&gt;Ahora podemos instalar cualquier paquete del registro ejecutando &lt;code&gt;npm install&lt;/code&gt; Por ejemplo podemos instalar &lt;a href="http://expressjs.com"&gt;expressjs&lt;/a&gt;, una serie de librerías para crear un servidor web:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
npm install --save express

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El modificador &lt;code&gt;--save&lt;/code&gt; indica a npm que queremos que guarde esta dependencia en el fichero del proyecto. Con express instalado localmente, podemos crear nuestro fichero &lt;code&gt;index.js&lt;/code&gt; con este contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const express = require('express')
const app = express()

app.get('/', function (req, res) {
  res.send('Hola desde Node!')
})

app.listen(3000, function () {
  console.log('Servidor creado y escuchando en el puerto 3000!')
})


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ejecutarlo en la consola:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
node index.js

Servidor creado y escuchando en el puerto 3000!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si abres un navegador y vas a 'localhost:3000' verás el mensaje 'Hola desde Node!'&lt;/p&gt;

&lt;p&gt;Esas son las herramientas básicas de desarrollo en Node.js. Módulos, un entorno de ejecución, el repositorio central de npm y JavaScript. Con lo que sabes ya puedes ir a explorar un poco el registro de npm o la documentación de express y comenzar a desarrollar tu propio servidor web :D&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Great github threads</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Sat, 30 Jun 2018 22:26:44 +0000</pubDate>
      <link>https://dev.to/juanmirod/great-github-threads-4975</link>
      <guid>https://dev.to/juanmirod/great-github-threads-4975</guid>
      <description>

&lt;p&gt;My favourite part about Github are the discussions. Like Twitter, Github allows you to watch the comments and code of well known software developers and have a pick of their way of thinking. The code is interesting, but a lot of times the code lacks the &lt;em&gt;WHY&lt;/em&gt;. Why the team or the developer chose to use a pattern or a design or why a feature made it to a language or not.&lt;/p&gt;

&lt;p&gt;You can see how big projects evolved thanks to issues, commits and PRs, and you can even participate in the debates and of course in the code. Before Github, all this information was in projects' newsletters, forums, chats... The information was more difficult to find and it would last less.&lt;/p&gt;

&lt;p&gt;Below there are a list of some Github threads that I considered interesting and worth of bookmarking. All of them, except for the last one, are about JavaScript, because it is my main language right now. Do you know any other great Github threads? Issues, PRs or maybe a gist that created an good discussion? Please leave it in the comments, I really love learning from others' points of views and their arguments. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/promises-aplus/promises-spec/issues/94"&gt;Promises are not monads&lt;/a&gt; Promises could have been very different if it wasn't for some opinionated developers that really wanted them to be like they are. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nodejs/CTC/issues/12"&gt;Promisify/awaitable in node&lt;/a&gt; Another one about promises and why the &lt;em&gt;promisify&lt;/em&gt; function was added to node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/facebook/immutable-js/issues/341"&gt;Immutable issue about typescript&lt;/a&gt; Discussion of ways of creating immutable data structures that work with typescript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ngrx/store/issues/23"&gt;About ngrx/store and immutable.js&lt;/a&gt; Immutable.js has trade offs as any other library. Immutability is great, but in JavaScript it is not idiomatic and it creates some friction...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://gist.github.com/substack/68f8d502be42d5cd4942#gistcomment-1365101"&gt;Browserify and webpack&lt;/a&gt; Browserify can do most of what webpack does, and even more in some cases, great gist and good discussion about the two tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/sindresorhus/ama/issues/10#issuecomment-117766328"&gt;One line modules&lt;/a&gt; Sindre Sorhus about one line modules and why npm made the &lt;em&gt;"utils scripts"&lt;/em&gt; folders irrelevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nodejs/node/pull/4765"&gt;Node-chakracore&lt;/a&gt; About adding the Microsoft core for JavaScript into Node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/torvalds/linux/pull/17#issuecomment-5654674"&gt;Linus Torvalds being... Linus Torvalds&lt;/a&gt; The last pearl in the list is not about JavaScript and not about a great discussion. Sometimes github allows you to see the bad parts of software development too. Linus is famous for being rude and coarse, this is just one of the multiple examples.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


</description>
      <category>github</category>
      <category>discuss</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Generadores en JavaScript</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Wed, 27 Jun 2018 22:35:27 +0000</pubDate>
      <link>https://dev.to/juanmirod/generadores-en-javascript-47c4</link>
      <guid>https://dev.to/juanmirod/generadores-en-javascript-47c4</guid>
      <description>&lt;p&gt;Los generadores son una herramienta de programación muy poderosa, pero difícil de entender cuando la vemos por primera vez. En este artículo trataré de definir de forma lo más sencilla posible qué son y como se usan los generadores y pasar a varios ejemplos prácticos en los que los generadores nos permiten simplificar código o directamente hacer cosas que no pensábamos que se pudieran hacer en JavaScript como funciones de evaluación perezosa y corutinas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es un generador?
&lt;/h3&gt;

&lt;p&gt;Un generador es una función especial en JavaScript que puede pausar su ejecución y retomarla en un punto arbitrario. Para definirlos utilizamos dos nuevas palabras reservadas del lenguaje: &lt;code&gt;function*&lt;/code&gt; y &lt;code&gt;yield&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Este es uno de los casos más claros en los que he encontrado que la barrera del idioma a veces dificulta la comprensión de ciertos conceptos. &lt;code&gt;yield&lt;/code&gt; es una palabra poco habitual en inglés, y para un no-nativo como yo, me suena totalmente fuera de contexto. Se traduce como &lt;em&gt;producir&lt;/em&gt; o &lt;em&gt;ceder&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trataré de explicar su funcionamiento con un ejemplo de código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;counterGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;
    &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;counterGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 0, done: false }&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 1, done: false }&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// { value: 2, done: false }&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// hasta el infinito y más allá!&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este sencillo ejemplo muestra el funcionamiento de un generador. El uso más habitual de los generadores es &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators"&gt;crear &lt;em&gt;Iteradores&lt;/em&gt;&lt;/a&gt;. Un &lt;em&gt;Iterador&lt;/em&gt; es un objeto que devuelve un elemento de una colección cada vez que llamamos a su método &lt;code&gt;.next&lt;/code&gt;. &lt;code&gt;counterGenerator&lt;/code&gt; devuelve un iterador que asignamos a la variable counter.&lt;/p&gt;

&lt;p&gt;Los generadores siempre devuelven un iterador y en el momento en el que llamamos al método &lt;code&gt;.next&lt;/code&gt; del iterador, éste ejecuta la función del generador hasta llegar al primer &lt;code&gt;yield&lt;/code&gt; que encuentra, que detiene la ejecución de la función y &lt;em&gt;produce&lt;/em&gt; un resultado, o dicho de otra forma, produce un elemento de la colección. &lt;/p&gt;

&lt;p&gt;El resultado es siempre un objeto con dos propiedades, &lt;code&gt;value&lt;/code&gt; y &lt;code&gt;done&lt;/code&gt;, en la primera está el valor producido por &lt;code&gt;yield&lt;/code&gt; y la segunda es para indicar si el iterador ha terminado, es decir, si ese era el último elemento de la colección. &lt;/p&gt;

&lt;p&gt;En la siguiente llamada a &lt;code&gt;.next&lt;/code&gt; la función continúa desde el &lt;code&gt;yield&lt;/code&gt; y hasta el siguiente &lt;code&gt;yield&lt;/code&gt;, y así hasta encontrar un &lt;code&gt;return&lt;/code&gt; que devolverá &lt;code&gt;true&lt;/code&gt; como valor de &lt;code&gt;done&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El iterador devuelto por &lt;code&gt;counterGenerator&lt;/code&gt; Puede usarse a su vez dentro de un bucle &lt;code&gt;for of&lt;/code&gt;, ya que estos bucles utilizan el interface del iterador para obtener el valor de cada iteración:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c1"&gt;// break detiene el bucle for como si hubiera encontrado done === true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// 10&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bucles infinitos y evaluación perezosa
&lt;/h3&gt;

&lt;p&gt;En el ejemplo anterior hemos usado todo el tiempo un bucle &lt;code&gt;while (true)&lt;/code&gt; sin bloquear o saturar la cpu y sin ninguna alerta por parte de node. Esto es así porque &lt;code&gt;yield&lt;/code&gt; pausa la &lt;br&gt;
ejecución de la función, y por lo tanto, pausa el bucle infinito, cada vez que produce un valor.&lt;/p&gt;

&lt;p&gt;Esto es lo que se llama &lt;em&gt;evaluación perezosa&lt;/em&gt; y es un concepto importante en lenguajes funcionales como Haskell. Básicamente nos permite tener listas o estructuras de datos &lt;em&gt;"infinitas"&lt;/em&gt; y operar sobre ellas, por ejemplo podemos tener un operador &lt;code&gt;take(n)&lt;/code&gt; que toma los N primeros elementos de una lista infinita:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;oddsGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;oddNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oddsGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// TODOS los números impares &lt;/span&gt;

&lt;span class="nx"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oddNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// toma 5 números impares&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="c1"&gt;// 5&lt;/span&gt;
&lt;span class="c1"&gt;// 7&lt;/span&gt;
&lt;span class="c1"&gt;// 9&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La evaluación perezosa permite construir este tipo de estructuras &lt;em&gt;"infinitas"&lt;/em&gt; o completas sin producir errores de ejecución y también son más eficientes en algoritmos de búsqueda, recorrido de árboles y cosas así, al evaluar el mínimo número de nodos necesarios para encontrar la solución. Para ver más usos y ventajas de la evaluación perezosa puedes ver &lt;a href="https://stackoverflow.com/questions/265392/why-is-lazy-evaluation-useful"&gt;este hilo de stackoverflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como añadido en JavaScript, los generadores nos permiten crear una sintaxis más legible en el uso de arrays. Podemos obtener los valores producidos por el generador en ES6 mediante el &lt;em&gt;spread operator&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;
    &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;// [ 0, 1, 2, 3, 4 ] &lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero cuidado con utilizar el &lt;em&gt;spread operator&lt;/em&gt; o los bucles for con listas infinitas como la de arriba:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;oddNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// bucle infinito!!&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;oddNumbers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// bucle infinito y 'out of memory', no podemos crear un array infinito en la memoria!!&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Async/await y corutinas
&lt;/h3&gt;

&lt;p&gt;Además de la generación de iteradores, los generadores nos permiten controlar la ejecución de funciones asíncronas gracias al mecanismo de pausa de la función de &lt;code&gt;yield&lt;/code&gt;. Para explicar por qué esto es importante, vamos a desviarnos un momento y hablar de &lt;code&gt;async/await&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Una de las funcionalidades más coreadas de ES7 son las nuevas construcciones &lt;code&gt;async&lt;/code&gt; y &lt;code&gt;await&lt;/code&gt;, que nos permiten ejecutar código asíncrono pero escribiéndolo de forma lineal, sin necesidad de pensar en callbacks o promesas. Veamos cómo funciona:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;helloDelayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;helloDelayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// a los 5 segundos aparece 'Hello'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo genial de &lt;code&gt;async/await&lt;/code&gt; es que el código de la función async es lineal, le hemos pasado una promesa a await y nos devuelde directamente el valor con el que se ha resuelto, esperando y deteniendo la ejecución de la función.&lt;/p&gt;

&lt;p&gt;No me voy a detener más en explicar cómo funciona, eso lo dejo para otro post, pero &lt;code&gt;async/await&lt;/code&gt; en realidad no es más que un uso concreto de los generadores, &lt;em&gt;azúcar sintáctico&lt;/em&gt; para usar un generador y evaluar una promesa, podríamos replicar esta funcionalidad, para una sola llamada (más adelante veremos la generalización) así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;helloDelayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nx"&gt;helloDelayed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta solución es más difícil de leer y de escribir, sobre todo por el doble &lt;code&gt;.next&lt;/code&gt; necesario para que funcione, y por la poca legibilidad del comando &lt;code&gt;yield&lt;/code&gt; en si mismo. Pero muestra una parte importante del funcionamiento de los generadores. &lt;/p&gt;

&lt;p&gt;Lo que está pasando aquí es que &lt;code&gt;hi&lt;/code&gt; recibe un generador como parámetro, lo ejecuta y llama una vez a &lt;code&gt;.next&lt;/code&gt; para ejecutar el generador hasta el yield y luego lo vuelve a llamar cuando tiene el resultado de la promesa para revolver el resultado al yield. &lt;/p&gt;

&lt;p&gt;Hasta ahora no habíamos hablado de esto para no complicar más, pero podemos añadir a la llamada a &lt;code&gt;.next&lt;/code&gt; un parámetro, que a su vez podemos capturar en una variable asignándola a &lt;code&gt;yield&lt;/code&gt;. Esta, para mi, es la funcionalidad más confusa de los generadores, pero es la clave para usarlos para ejecutar llamadas asíncronas o corutinas como veremos en los siguientes ejemplos. Veamos un pequeño ejemplo de como funciona:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;counterGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;counterGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;// { value: 0, done: false }&lt;/span&gt;
&lt;span class="c1"&gt;// el primer 'next' no imprime nada porque el generador se ejecuta solo hasta el yield&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ho&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;// ho&lt;/span&gt;
&lt;span class="c1"&gt;// { value: 1, done: false }&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;// hu&lt;/span&gt;
&lt;span class="c1"&gt;// { value: 2, done: false }&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este mecanismo nos da una forma de comunicarnos con el generador, algo muy potente, aunque en mi opinión con una sintaxis difícil de leer y nada clara. Los generadores no son una herramienta que hay que usar con moderación, pero nos permiten hacer cosas que estarían fuera del alzance de JavaScript si no fuera con ellos, como el ejemplo que veremos a continuación.&lt;/p&gt;

&lt;p&gt;Generalizando el código de helloDelayed, se puede construir una función que controle la ejecución de funciones asíncronas prácticamente igual a como hace &lt;code&gt;async/await&lt;/code&gt;, veamos un ejemplo que lee dos ficheros (ejemplo tomado de &lt;a href="https://medium.com/@tjholowaychuk/callbacks-vs-coroutines-174f1fe66127"&gt;este post de TJ HoloWaychuck&lt;/a&gt;, que recomiendo leer, el código original usa callbacks, pero lo he modificado para usar promesas, dos ejemplos por el precio de uno &lt;em&gt;;)&lt;/em&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;README.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código, sí se parece mucho más al de &lt;code&gt;async/await&lt;/code&gt;, es más, si cambiamos &lt;code&gt;thread&lt;/code&gt; por &lt;code&gt;async&lt;/code&gt; y imaginamos que &lt;code&gt;yield&lt;/code&gt; es &lt;code&gt;await&lt;/code&gt; es prácticamente igual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;README.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este ejemplo básico es una simplificación de la librería &lt;a href="https://github.com/tj/co"&gt;Co&lt;/a&gt;, que nos permite escribir este tipo de código asíncrono de forma lineal y con la seguridad de que captura todas las excepciones de forma parecida a como hacen las Promesas.&lt;/p&gt;

&lt;p&gt;Técnicamente esto no son corutinas. En realidad, cuando hablamos de generadores, hablamos de &lt;a href="https://en.wikipedia.org/wiki/Coroutine#Comparison_with_generators"&gt;&lt;em&gt;'semicorutinas'&lt;/em&gt;&lt;/a&gt; porque los generadores no son tan flexibles como las corutinas de lenguajes como Go, pero diremos que son equivalentes a corutinas, aún sabiendo que estamos simplificando, porque es la herramienta que tenemos para esta función en JavaScript a nivel nativo. &lt;/p&gt;

&lt;p&gt;En cuando a otras librerías para corutinas, &lt;a href="https://github.com/fibjs/fibjs"&gt;fibjs&lt;/a&gt; y &lt;a href="https://github.com/laverdet/node-fibers"&gt;node-fibers&lt;/a&gt; son implementaciones de &lt;em&gt;'fibers'&lt;/em&gt; que podríamos traducir como &lt;em&gt;"fibras"&lt;/em&gt; o &lt;em&gt;"hilos ligeros"&lt;/em&gt; que es más flexible que los generadores y que algunos desarrolladores &lt;a href="https://github.com/nodejs/node/issues/9131"&gt;quieren incluir en el núcleo de Node.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Los generadores y las corutinas son herramientas avanzadas del lenguaje que seguramente no tengas que utilizar directamente a no ser que hagas desarrollo de sistemas o librerías, pero de las que podemos sacar provecho en nuestro código con librerías como &lt;code&gt;Co&lt;/code&gt;, &lt;code&gt;node-fibers&lt;/code&gt; o el nuevo &lt;code&gt;async/await&lt;/code&gt; nativo. Espero que estos ejemplos hayan resuelto algunas dudas y generado aun más dudas e interés por el lenguaje y sirva como introducción a todo este tema.&lt;/p&gt;

&lt;p&gt;Otra lectura recomendada para profundizar en los Generadores es el libro de Kyle Simpson ES6 and Beyond, y en concreto &lt;a href="https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch3.md#generators"&gt;el capítulo sobre Iteradores y Generadores&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Tests unitarios en JavaScript con Jasmine</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Thu, 07 Jun 2018 21:54:12 +0000</pubDate>
      <link>https://dev.to/juanmirod/tests-unitarios-en-javascript-con-jasmine-118e</link>
      <guid>https://dev.to/juanmirod/tests-unitarios-en-javascript-con-jasmine-118e</guid>
      <description>&lt;p&gt;Los tests unitarios son una herramienta excelente para prevenir bugs en ejecución y para describir el comportamiento que debe tener el código. Además, y &lt;a href="http://research.microsoft.com/en-us/groups/ese/nagappan_tdd.pdf"&gt;sobre todo si se realizan antes que el código&lt;/a&gt; de la aplicación (lo que se conoce como &lt;strong&gt;TDD&lt;/strong&gt;), los test unitarios ayudan a estructurar mejor el código, hacerlo más modular e independiente y además ayudan a dividir los problemas y hacerlos más sencillos de programar.&lt;/p&gt;

&lt;p&gt;En JavaScript, &lt;a href="https://jasmine.github.io/2.4/introduction.html"&gt;Jasmine&lt;/a&gt; es un framework de test que permite crear tests fáciles de leer de forma que sirven también de documentación para el código. Así, usando Jasmine, si queremos escribir una suit de tests para una función que suma dos números llamada 'add' la escribiríamos así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should add two numbers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="c1"&gt;// código del test&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should throw an error if you try to add strings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="c1"&gt;// código del test&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos a ver algunos ejemplos de código y sus correspondientes tests. El proyecto es una sencilla calculadora en JavaScript, pero es diferente a los típicos ejemplos de calculadoras en javascript, ya que en esta no se utiliza eval para calcular los resultados, sino que el input se valida y las operaciones están limitadas a las que están definidas. Para ello he creado dos pequeños módulos, uno para la lógica y otro para el interface. &lt;/p&gt;

&lt;p&gt;El proyecto es un ejemplo sencillo, según las especificaciones de cada proyecto serán pertinentes más o menos tests y habrá que controlar casos más concretos, espero que este proyecto sirva de ejemplo aunque no sea muy exhaustivo ni tenga muchos requisitos.&lt;/p&gt;

&lt;p&gt;Empezaremos con los test de la clase que controla el funcionamiento de la calculadora por ser más sencillo. Cuando tienes una clase que no realiza operaciones de entrada salida, ni modifica el DOM o interacciones del usuario es mucho más sencillo escribir los tests. A eso me refería antes con que escribir los tests primero te ayuda a separar el código y a promueve mucho el principio de que cada función se encargue sólo de una cosa. En problemas fáciles como este de la calculadora, es fácil verse tentado a poner todo el código junto, meter un par de funciones en el código que maneja el interface y listo. &lt;/p&gt;

&lt;p&gt;El problema viene a largo plazo, cuando el cliente dice que además de calcular tiene que mostrar el resultado intermedio y luego te dicen que al meter un símbolo que no debería hacer nada la calculadora da un error muy feo, o que debería poder guardar en memoria un resultado... Y empezamos a poner más código en esas funcioncitas en medio del interface y esas funcioncitas van creciendo hasta tener cientos de líneas de código y... seguro que ya sabes por donde voy. Nuestra sencilla calculadora, que habíamos programado en un par de horas, crece hasta convertirse en una pesadilla de mantener y de modificar. Y además nuestro jefe no entiende cómo puede ser que hicieramos la calculadora en un día pero ahora para añadir una funcionalidad &lt;em&gt;obvia&lt;/em&gt; tardemos una semana.&lt;/p&gt;

&lt;p&gt;Por eso es por lo que en esta ocasión vamos a usar TDD y vamos a escribir primero unos tests de lo que queremos que nuestra calculadora haga:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Calculator.spec.js&lt;/span&gt;
&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should have a storeAction function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storeAction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the last result for unkown actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HI&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should add numbers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESULT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should multiply numbers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MULTIPLY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESULT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="p"&gt;});&lt;/span&gt; 

&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bien, ya sabemos lo que queremos, una calculadora que sume y multiplique, y que no admita cualquier cosa por la entrada. Para implementar esto nuestro Módulo calculadora debe tener una función &lt;code&gt;storeAction&lt;/code&gt; que será la que utilizaremos para introducir la siguiente operación o número sobre el que la calculadora debe operar, imitando el funcionamiento normal de una calculadora clásica. La functión &lt;strong&gt;beforeEach&lt;/strong&gt; es una función de &lt;em&gt;Jasmine&lt;/em&gt; que se ejecutará antes de cada función &lt;strong&gt;it&lt;/strong&gt; y que nos sirve para asegurarnos de que antes de cada test partimos del mismo estado inicial.&lt;/p&gt;

&lt;p&gt;Estos tests están bien para comenzar, pero si nos fijamos veremos que hay muchos más casos que controlar, como ¿qué pasa si añado dos números seguidos? ¿y si añado dos operaciones? ¿Donde está el test para la función de &lt;em&gt;RESET&lt;/em&gt;? Todos estos test deberán ir añadiendose y satisfaciéndose en el código.&lt;/p&gt;

&lt;p&gt;Si solo tenemos los tests y los ejecutamos en la línea de comandos o en el navegador, veremos que fallan. Para ejecutarlos lo más sencillo es crear un fichero &lt;em&gt;html&lt;/em&gt; en el que añadiremos los scripts de jasmine que están alojados en el CDN de jsdeliver. A continuación añadimos los ficheros js de nuestra aplicación y los ficheros que contienen los tests para los diferentes módulos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Sample Unit tests runner&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/jasmine/2.4.1/jasmine.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/jasmine/2.4.1/jasmine.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/jasmine/2.4.1/jasmine-html.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/jasmine/2.4.1/boot.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"calculator.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"calculator.spec.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;


&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al abrir este fichero en el navegador, Jasmine creará un pequeño interface y listará los tests junto con los resultados y los errores que hayan ocurrido. En este caso, si sólo tenemos el fichero de especificaciones, todos los tests fallarán.&lt;/p&gt;

&lt;p&gt;Para satisfacerlos, deberemos crear el módulo &lt;strong&gt;Calculator&lt;/strong&gt; y añadir la función &lt;strong&gt;storeAction&lt;/strong&gt; con la funcionalidad suficiente para que satisfaga los tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Calculator.js&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strict mode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nx"&gt;lastResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nx"&gt;setLastResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;lastResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 

    &lt;span class="na"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;isFinite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;storeAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;setLastResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastResult&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MULTIPLY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;setLastResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastResult&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;setLastResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// new operation&lt;/span&gt;

        &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="nx"&gt;setLastResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="nx"&gt;setLastResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;}&lt;/span&gt; 

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lastResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;})();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código satisface los tests de arriba y algunos más. Aún nos quedaría añadir la funcionalidad para restar, dividir, limpiar el input, etc. Puedes ver el ejemplo algo más completo en &lt;a href="https://thimbleprojects.org/juanmirod/56250/"&gt;este thimble&lt;/a&gt;. Para ver el resultado de los tests haz click en el fichero 'test.html'.&lt;/p&gt;

&lt;p&gt;Si te fijas, en ese projecto no hay tests para la parte del interface de la calculadora. Hay funciones del interface que no tiene mucho sentido testar, el markup puede cambiar sin alterar la funcionalidad y no tiene mucho sentido escribir tests para algo así. Pero sí que podemos escribir tests que verifiquen que, cuando hago click en un botón o pulso una tecla, se llama a la función adecuada. Estos tests son algo más complicados  ya que tenemos que capturar los eventos y espiar las funciones que estos deben llamar. &lt;/p&gt;

&lt;p&gt;Thimble es una buena herramienta para practicar TDD ya que el proyecto se va guardando y la vista se actualiza de forma automática. Pero necesitamos de conexión a internet y no tiene la velocidad y las ayudas de editores como Sublime o VSCode. Para conseguir que la vista se actualice automáticamente como en Thimble en nuestro proyecto en local podemos utilizar varias herramientas diferentes. En el siguiente artículo me centraré en cómo añadir &lt;a href="https://karma-runner.github.io/0.13/index.html"&gt;Karma&lt;/a&gt; a nuestro proyecto y utilizarlo para trabajar con TDD. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>spanish</category>
      <category>testing</category>
    </item>
    <item>
      <title>Ámbito léxico y de bloque en JavaScript</title>
      <dc:creator>Juan Miguel Rodriguez Ceron</dc:creator>
      <pubDate>Thu, 07 Jun 2018 21:45:27 +0000</pubDate>
      <link>https://dev.to/juanmirod/mbito-lxico-y-de-bloque-en-javascript-868</link>
      <guid>https://dev.to/juanmirod/mbito-lxico-y-de-bloque-en-javascript-868</guid>
      <description>&lt;p&gt;El ámbito de las variables en JavaScript puede ser un poco confuso a veces, pero en realidad sólo hay que seguir un par de reglas para saber a qué ámbito pertenece una variable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;En JavaScript &lt;strong&gt;las funciones tienen su propio ámbito léxico&lt;/strong&gt;, lo que quiere decir que depende de cómo son declaradas en el código y no de cuando se ejecutan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sólo las funciones&lt;/strong&gt; pueden crear un nuevo ámbito y como excepción, los bloques &lt;strong&gt;catch&lt;/strong&gt; también crean su propio ámbito. Con la introducción de las variables &lt;code&gt;let&lt;/code&gt; y &lt;code&gt;const&lt;/code&gt; en ES6, también tenemos a nuestra disposición ámbito de bloque, ver más abajo para ver qué significa esto.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;¿Cómo funciona este ámbito léxico de las funciones? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A la hora de decidir a qué ámbito pertenece una variable, el compilador de JavaScript comprueba si la variable está declarada dentro de la función donde se invoca (ámbito local de la función) si no es así, busca en el ámbito de la función que la contenga y así hasta llegar al ámbito global. &lt;strong&gt;Si la variable no fue declarada en ningún momento, el compilador la declara como variable global&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En 'Strict mode' el compilador no creará la nueva variable en ámbito global sino que devolverá un error por variable no declarada.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La mejor forma de ver cómo funcionan estas reglas es probándolas en directo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;//'use strict'; // descomentar para ver el error al usar la variable bye&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Global: I am global. &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ObjectWithPrivateVariables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ObjectDefinition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Esta variable está definida dentro del ámbito de la functión ObjectDefinition&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Object: Hello. &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="c1"&gt;//var bye; // descomentar para arreglar la fuga de la variable bye al ámbito global&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sayHi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;returnsAGreeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// El ámbito de esta función está dentro del ámbito de OnjectDefinition&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;sayBye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;byes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;bye&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Good bye!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;bye&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ObjectWithPrivateVariables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;newObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sayHi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="c1"&gt;// Accede a la variable Global&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;newObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sayBye&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;bye&lt;/span&gt; &lt;span class="c1"&gt;// Esta variable se ha declarado como global y podemos acceder a ella, cuidado!!&lt;/span&gt;
&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;sayHi&lt;/span&gt; &lt;span class="c1"&gt;// sayHi es undefined&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://jsfiddle.net/juanmirod/zgsgqz2j/"&gt;Editar en jsfiddle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es interesante jugar un poco con el script, mover las declaraciones de sitio y ver que pasa. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok, lo he pillado y ahora ¿Qué es eso del ámbito de bloque?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En ES6 se introdujeron los tipos de variable &lt;code&gt;let&lt;/code&gt; y &lt;code&gt;const&lt;/code&gt; que no funcionan como las variables &lt;code&gt;var&lt;/code&gt; sino que tienen ámbito de bloque (block scope). Esto significa que estas variables existen dentro del bloque donde son declaradas, independientemente de si ese bloque es una función, una condición o un bucle. Además, las variables declaradas con let y const no se pueden utilizar antes de ser declaradas. &lt;/p&gt;

&lt;p&gt;Esto es muy útil para declarar variables dentro de bucles o condiciones y que estas variables no se &lt;em&gt;"filtren"&lt;/em&gt; al ámbito de la función. Siempre es más fácil explicarlo con un poco de código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;countTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// console.log(i) // descomentar dará un error, i no está definida&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// console.log(i) // descomentar dará un error, i no está definida&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;countTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://jsfiddle.net/juanmirod/r2wLyvg3/"&gt;Editar en jsfiddle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algo muy curioso de este pequeño código es el diferente resultado de los dos primeros &lt;code&gt;console.log&lt;/code&gt; Las variables &lt;code&gt;let&lt;/code&gt; y &lt;code&gt;const&lt;/code&gt; no permiten ser usadas antes de ser declaradas, pero las variables declaradas con &lt;code&gt;var&lt;/code&gt; sí. Esto es debido a una propiedad que se llama &lt;code&gt;hoisting&lt;/code&gt;, que quiere decir que el compilador de JavaScript hace una primera pasada por todo el código para ver qué variables y funciones hemos definido y asignarles su ámbito. Hasta que la ejecución no llegue al punto de la asignación la variable tendrá el valor &lt;code&gt;undefined&lt;/code&gt;. Esto no ocurre con &lt;code&gt;let&lt;/code&gt; y &lt;code&gt;const&lt;/code&gt;, que no son creadas hasta que la ejecución no llega al punto donde son declaradas. Así, si creamos una variable de bloque dentro de una condición que no se cumple, nunca se creará, y estaremos ahorrando ese tiempo y esa memoria.&lt;/p&gt;

&lt;p&gt;Estas propiedades hacen que las variables &lt;code&gt;let&lt;/code&gt; y &lt;code&gt;const&lt;/code&gt; sean consideradas más fáciles de entender, que es lo importante, y actualmente las guías de estilo de código recomienden su uso sobre var. Si usas un linter, lo más seguro es que, si usas var, te lo marque como un warning o un error.&lt;/p&gt;

&lt;p&gt;La diferencia entre let y const es que las variables &lt;code&gt;const&lt;/code&gt; no se pueden reasignar, con lo que en el caso de valores escalares (cadenas, números y booleanos) son efectivamente constantes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="c1"&gt;// ningún problema&lt;/span&gt;
&lt;span class="c1"&gt;// y = 8 // Error, 'y' no puede volver a asignarse por ser una constante&lt;/span&gt;

&lt;span class="c1"&gt;// pt = 'otracosa' // Error, pt no puede volver a asignarse&lt;/span&gt;

&lt;span class="nx"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="c1"&gt;// sin problema, ahora pt.x vale 15 en lugar de 0&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo de código puede verse que no ocurre así con los objetos, porque lo que no se puede modificar es la referencia que contiene esa variable, pero sí podremos modificar las propiedades internas del objeto, (a no ser que estén congeladas, pero de eso hablaremos otro día).&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>spanish</category>
      <category>scope</category>
      <category>ámbito</category>
    </item>
  </channel>
</rss>
