<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Js on dev.endevour</title><link>https://devendevour.iankulin.com/tags/js/</link><description>Recent content in Js on dev.endevour</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 17 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://devendevour.iankulin.com/tags/js/index.xml" rel="self" type="application/rss+xml"/><item><title>Node.js built in test runner</title><link>https://devendevour.iankulin.com/node-js-built-in-test-runner/</link><pubDate>Mon, 17 Mar 2025 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/node-js-built-in-test-runner/</guid><description>&lt;p&gt;For the longest time, I&amp;rsquo;ve been using &lt;a href="https://mochajs.org/" target="_blank" rel="noopener"&gt;Mocha&lt;/a&gt; (test runner) and &lt;a href="https://www.chaijs.com/" target="_blank" rel="noopener"&gt;Chai&lt;/a&gt; (assertion library) for my JS testing. They are reliable old friends.&lt;/p&gt;
&lt;p&gt;One of the effects of the existence of &lt;a href="https://bun.sh/" target="_blank" rel="noopener"&gt;Bun&lt;/a&gt; and &lt;a href="https://deno.com/" target="_blank" rel="noopener"&gt;Deno&lt;/a&gt; has been to spur Node onto adding some new features, so after appearing as an experimental feature in 18, the Node test runner dropped in Node 20.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not sure if the familiar unit test layout of Mocha and Node is inherited from Jest, or comes from older testing frameworks of which JUnit and NUnit were the first ones I&amp;rsquo;d ever used. Before that I just used to write tests as lumps of assertions in regular code - which worked but wasn&amp;rsquo;t as pleasant to use as a proper unit test setup. Regardless, the system of bundling a few tests together and having them all run and spit out green ticks is not a new one.&lt;/p&gt;</description></item><item><title>A bit of web-scraping with Cheerio</title><link>https://devendevour.iankulin.com/a-bit-of-web-scraping-with-cheerio/</link><pubDate>Mon, 17 Feb 2025 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/a-bit-of-web-scraping-with-cheerio/</guid><description>&lt;p&gt;I had an idea for a little holiday project that required a list of episodes from &lt;a href="https://therestishistory.supportingcast.fm/" target="_blank" rel="noopener"&gt;The Rest Is History&lt;/a&gt; podcast. On their &amp;lsquo;Episodes&amp;rsquo; page, they have a player, and a list of post entries for the most recent eighteen podcasts. There is a &amp;lsquo;show all&amp;rsquo; button, but it doesn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/screen-shot-2025-01-05-at-8.47.03-am.png" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;The player does contain the full list of episodes (about 600) including a number of duplicates, so I expected if I inspected the network calls that I&amp;rsquo;d see a JSON package arriving with what I wanted. This is what I almost always find these days so I&amp;rsquo;ve had very little call to do any real web scraping - it&amp;rsquo;s normally just a matter of locating the endpoint and perhaps extracting an API key from a header.&lt;/p&gt;</description></item><item><title>React code is not HTML</title><link>https://devendevour.iankulin.com/react-code-is-not-html/</link><pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/react-code-is-not-html/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/pucker_the_react_atom_logo_fighting_with_some_html_4b0d18eb-b17f-471f-a42c-a99e160b1231-copy.jpg" alt="The React atom logo fighting with some HTML - midjourney, edited" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;I was looking at this ugly code in a React app:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;div style={{overflow: &amp;#39;scroll&amp;#39;, border: &amp;#39;1px solid black&amp;#39;, height: &amp;#39;600px&amp;#39; }}&amp;gt;
 { props.children }
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since I don&amp;rsquo;t need any of those CSS properties to change at any stage, I could just convert it to pure HTML/CSS right? Well no:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/screen-shot-2023-01-09-at-4.26.54-pm.png" alt="" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;The newbie trap I&amp;rsquo;ve fallen for here is that although that &lt;code&gt;&amp;lt;div style= tag&lt;/code&gt; looks like HTML, it&amp;rsquo;s actually not. It&amp;rsquo;s not a template that will be filled out in the build step, it&amp;rsquo;s React code that will be used to mutate the virtual DOM.&lt;/p&gt;</description></item><item><title>De-structuring objects in JS</title><link>https://devendevour.iankulin.com/de-structuring-objects-in-js/</link><pubDate>Fri, 20 Jan 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/de-structuring-objects-in-js/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/pucker_robot_repair_shop_wth_several_humanoid_robots_in_state_o_c5ef7630-fb2a-4dec-acd5-dfb9b9f478ac.jpg" alt="robot repair shop wth several humanoid robots in state of disrepair, cinematic lighting, dust in the air - midjourney" class="img-responsive"&gt; &lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve worked through my first React tutorial app, and obviously that&amp;rsquo;s a lot - I&amp;rsquo;m struct by how messy mixing HTML, JS and React is.&lt;/p&gt;
&lt;p&gt;One language feature that&amp;rsquo;s being used quite a bit, and that is apparently a JS ability I&amp;rsquo;d never seen is &amp;lsquo;destructuring&amp;rsquo; object properties. It&amp;rsquo;s very cool and obviously useful. It&amp;rsquo;s a way of extracting just the properties you need from an object and then using them without accesing them via the object. An example will make it clearer.&lt;/p&gt;</description></item><item><title>Calculator</title><link>https://devendevour.iankulin.com/calculator-2/</link><pubDate>Mon, 16 Jan 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/calculator-2/</guid><description>&lt;p&gt;I&amp;rsquo;ve been doing a bit of driving during the holidays, which means a lot of podcast listening. An episode of &lt;a href="https://topenddevs.com/podcasts/javascript-jabber/episodes/splatty-doo-and-other-javascript-features-you-should-avoid-jsj-543" target="_blank" rel="noopener"&gt;JavaScript Jabber about JS features you should never use&lt;/a&gt; sparked my interest in &lt;code&gt;[eval()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)&lt;/code&gt;. &lt;code&gt;eval()&lt;/code&gt; takes whatever you pass it in a string and executes it in the JS engine. This is a crazy concept if you&amp;rsquo;ve come from complied languages, and has obvious security implications. As with dynamic typing, I&amp;rsquo;m trying to force myself out of my comfort zone to embrace JS&amp;rsquo;s unique talents so I was keen to try &lt;code&gt;eval()&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>CWD - 185 - Problem solving</title><link>https://devendevour.iankulin.com/cwd-185-problem-solving/</link><pubDate>Sat, 14 Jan 2023 00:00:00 +0000</pubDate><guid>https://devendevour.iankulin.com/cwd-185-problem-solving/</guid><description>&lt;p&gt;&lt;img src="https://devendevour.iankulin.com/images/pucker_c-3po_from_star_wars_on_tatooine_playing_tic-tac-toe_on__66c1149e-de97-45d4-9863-18181aa54cf7.jpg" alt="C-3PO from Star Wars on Tatooine, playing Tic-tac-toe on the side of a crashed spaceship - MidJourney" class="img-responsive"&gt; &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/* 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;Question 1: Clean the room function: given an input of [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20], 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;make a function that organizes these into individual array that is ordered. For example 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;answer(ArrayFromAbove) should return: [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctrFunction1&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;inputArray&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// copy the array since we&amp;#39;re mutating it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [...&lt;span style="color:#a6e22e"&gt;inputArray&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;array&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;number&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;] &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;undefined&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// this property does not exist, so add it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;push&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;number&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// object now contains arrays for each number, but the ones with a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// single element need degloved
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;property&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;property&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;property&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;property&lt;/span&gt;][&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// now turn back to array 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Object.&lt;span style="color:#a6e22e"&gt;values&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;numberObject&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array1&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;591&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;392&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;391&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;transformedArray1&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ctrFunction1&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;array1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;transformedArray1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [1, 1, 1, 1], [2, 2, &amp;#39;2&amp;#39;], 4, 5, 10, [20, 20], 391, 392, 591]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="line-10"&gt;Line 10&lt;/h4&gt; &lt;p&gt;When I&amp;rsquo;m looking at a function, I&amp;rsquo;d prefer not to also have to hold global state in my head - so I&amp;rsquo;m all for functional programming as far as that goes. I&amp;rsquo;m less concerned about side effects, so I wouldn&amp;rsquo;t always bother to copy a parameter like this, but the argument is stronger for an array than an object since in other languages an array might be a value type.&lt;/p&gt;</description></item></channel></rss>