<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>JavaScript on Much Ado About IT</title><link>https://it.knightnet.org.uk/tags/javascript/</link><description>
Recent content about JavaScript from Much Ado About IT |
Ramblings and rantings from IT Architect &amp; Designer, Julian Knight</description><generator>Hugo | gohugo.io | Theme twenty-sixteen</generator><language>en-gb</language><copyright>This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.</copyright><lastBuildDate>Mon, 24 Apr 2023 21:27:28 +0000</lastBuildDate><atom:link href="https://it.knightnet.org.uk/tags/javascript/feed.xml" rel="self" type="application/rss+xml"/><item><title>How to reliably detect the object type of a JavaScript variable?</title><link>https://it.knightnet.org.uk/kb/node-js/object-type-detection/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/object-type-detection/</guid><pubDate>Sun, 07 Jun 2020 14:30:54 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/object-type-detection/</guid><description><div>The nature of JavaScript means that everything is treated as an object (sort of). It can be remarkably hard to reliably detect what type of object something is and there isn't a single function in JavaScript that can be used in all cases. So how do we do it? Here are some options</div><div>&lt;p>The &amp;ldquo;official&amp;rdquo; way is to use &lt;code>Object.prototype.toString.call(objectToTest)&lt;/code>. This will work no matter what the object is, even &lt;code>null&lt;/code> or &lt;code>undefined&lt;/code>. However, it is relatively quite slow.&lt;/p>
&lt;p>A &lt;a href="https://stackoverflow.com/a/49506047/1309986">quicker way&lt;/a> is probably to use &lt;code>objectToTest.__proto__.constructor.name&lt;/code>. However, note that this will fail (as do many other methods) if the object is &lt;code>null&lt;/code> or &lt;code>undefined&lt;/code>.&lt;/p>
&lt;h2 id="simple-function">Simple function&lt;/h2>
&lt;p>This simple function provides an easy to use way to return the object type and a list of simple type ENUM&amp;rsquo;s to compare against.&lt;/p>
&lt;p>Note that using &lt;code>Object.prototype.toString.call(prop)&lt;/code> is a fairly slow operation and therefore this should be avoided when maximum performance is required.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">types&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;get&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">prop&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">Object&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">prototype&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">toString&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">call&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">prop&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;null&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Null]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;object&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Object]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;array&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Array]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;string&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object String]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;boolean&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Boolean]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Number]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;date&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;[object Date]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Used as:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">types&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">prop&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nx">types&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">number&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It can, of course, be extended with your own bespoke object types.&lt;/p>
&lt;p>This is taken from an &lt;a href="https://stackoverflow.com/a/32297474/1309986">answer&lt;/a> to the StackOverflow Question: &lt;a href="https://stackoverflow.com/questions/7893776/the-most-accurate-way-to-check-js-objects-type">The most accurate way to check JS object&amp;rsquo;s type?&lt;/a>.&lt;/p></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>Creating a notification in the Admin UI</title><link>https://it.knightnet.org.uk/kb/nr-qa/notifying-admin/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/nr-qa/notifying-admin/</guid><pubDate>Sun, 16 Jun 2019 19:22:16 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/nr-qa/notifying-admin/</guid><description><div>Node-RED's admin UI has a built-in notification (toast) pop-up message feature.
This article explains how to use it when creating custom nodes as it isn't currently well documented.</div><div>&lt;p>&lt;code>RED.notify('Your message here', options)&lt;/code>&lt;/p>
&lt;p>This can be called from the script in your admin ui code &lt;code>&amp;lt;nodeName&amp;gt;.html&lt;/code>.&lt;/p>
&lt;p>By default, the notification will disappear after a few seconds.&lt;/p>
&lt;h1 id="options">Options&lt;/h1>
&lt;ul>
&lt;li>&lt;code>type&lt;/code>: {success|warning|error=} Adds style to the message box.&lt;/li>
&lt;li>&lt;code>fixed&lt;/code>: {boolean=false} Defaults to false, the notification will auto-remove after a few seconds.&lt;/li>
&lt;li>&lt;code>modal&lt;/code>: {boolean=false} If true, no other user interactions are allowed until the notification has cleared.&lt;/li>
&lt;li>&lt;code>timeout&lt;/code>: {ms=5000}: Specify the time in milliseconds a non-fixed notification will be displayed for.&lt;/li>
&lt;li>&lt;code>id&lt;/code>: {string=} Allows a notification to be updated.&lt;/li>
&lt;li>&lt;code>width&lt;/code>: {px=} Desired width in pixels. (Will be limited to the parent width)&lt;/li>
&lt;/ul>
&lt;h1 id="methods">Methods&lt;/h1>
&lt;ul>
&lt;li>&lt;code>.close()&lt;/code>: Close the notification (useful if &lt;code>fixed&lt;/code> option is &lt;code>true&lt;/code>).&lt;/li>
&lt;li>&lt;code>update&lt;/code>&lt;/li>
&lt;li>&lt;code>hideNotification&lt;/code>&lt;/li>
&lt;li>&lt;code>showNotification&lt;/code>&lt;/li>
&lt;/ul>
&lt;h1 id="example">Example&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">let&lt;/span> &lt;span class="nx">myNotification&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">RED&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">notify&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;My message in a box&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">modal&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">fixed&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">type&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;warning&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">buttons&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;text&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;cancel&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;click&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">myNotification&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;text&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;okay&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;class&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;primary&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;click&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">myNotification&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="references">References&lt;/h1>
&lt;ul>
&lt;li>&lt;a href="https://discourse.nodered.org/t/node-red-admin-ui-display-message-to-user/12290">https://discourse.nodered.org/t/node-red-admin-ui-display-message-to-user/12290&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/node-red/node-red/blob/ccc3809daa3b03e7171cb6f4ccf4d6e0f1188bef/packages/node_modules/%40node-red/editor-client/src/js/ui/notifications.js#L16">https://github.com/node-red/node-red/blob/ccc3809daa3b03e7171cb6f4ccf4d6e0f1188bef/packages/node_modules/%40node-red/editor-client/src/js/ui/notifications.js#L16&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/node-red/node-red/wiki/API-Reference">https://github.com/node-red/node-red/wiki/API-Reference&lt;/a> (old but has some things not documented elsewhere)&lt;/li>
&lt;/ul></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/node-red">Node-RED</category><category domain="https://it.knightnet.org.uk/tags/node.js">Node.JS</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category></item><item><title>Cleaning up npm package install problems</title><link>https://it.knightnet.org.uk/kb/nr-qa/clean-up-npm/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/nr-qa/clean-up-npm/</guid><pubDate>Wed, 05 Jun 2019 07:05:39 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/nr-qa/clean-up-npm/</guid><description><div>Node-RED uses npm to manage package installations such as its nodes.
Sometimes, you can get into a situation where you start getting lots of npm installation or removal issues and it feels like you are going round in circles trying to fix things. If so, time to call it a day and to get drastic! Here, I try to explain an easy way to fix things quickly and completely without side effects.</div><div>&lt;p>Node-RED is built over Node.js which uses &lt;code>npm&lt;/code> as its library (AKA package) manager. It is great to have a standard mechanism to manage libraries but the complexities of managing JavaScript based packages sometimes trips things up.&lt;/p>
&lt;p>Once you&amp;rsquo;ve tried for a bit to understand what the issues are, it may be time to call time and get drastic.&lt;/p>
&lt;p>The following commmands will clean out the packages installed for your live instance of Node-RED - assuming you have it installed via the &amp;ldquo;standard&amp;rdquo; default method. If not, you will need to adjust the folder you operate in.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ~/.node-red
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm package-lock.json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -R node_modules
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That will cleanly reinstall all of the packages marked in your &lt;code>package.json&lt;/code> file. So make sure that is correct first. Every time you install a package (as long as you have reasonably up-to-date versions of Node.js and npm) whether from the NR admin ui or command line, it gets added to package.json.&lt;/p>
&lt;p>I now always remove the lock file as well if I&amp;rsquo;m having issues as that can be the cause of some issues. The lock file isn&amp;rsquo;t generally needed in NR installations.&lt;/p>
&lt;p>Note, as always, I&amp;rsquo;ve assumed you have a &amp;ldquo;standard&amp;rdquo; install of Node-RED which puts your userDir as &lt;code>~/.node-red&lt;/code> (and the equivalent on Windows). If you use an installation scheme like mine, it will be in a different place as noted by the command used to start NR.&lt;/p></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/node-red">Node-RED</category><category domain="https://it.knightnet.org.uk/tags/npm">npm</category><category domain="https://it.knightnet.org.uk/tags/node.js">Node.JS</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/debugging">Debugging</category></item><item><title>Analysing the Performance of Node-RED</title><link>https://it.knightnet.org.uk/kb/nr-qa/analysing-performance/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/nr-qa/analysing-performance/</guid><pubDate>Fri, 19 Apr 2019 13:23:06 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/nr-qa/analysing-performance/</guid><description><div>Node-RED is a powerful platform for prototyping and rapid development but it is complex. It has a lot of moving parts and it can be hard to know what might be causing performance bottlenecks.
This article tries to give some hints and tips about analysing those bottlenecks and how to resolve them.</div><div>&lt;p>Sorry, this is draft and far from complete. Please leave comments if you have something useful to add. Thought I would publish anyway in case anyone finds it useful. I will try to come back to it in the future. If you leave a comment, it will remind me. :-)&lt;/p>
&lt;h1 id="platform">Platform&lt;/h1>
&lt;p>Before starting more detailed analysis, the first thing to do is to look at the platform being used to run Node-RED.&lt;/p>
&lt;p>Often, something like a Raspberry Pi or other single-board computer (SBC) is being used. They have very limited resources and often slow storage (e.g. SD-Cards). So it is very easy to overload them and kill performance.&lt;/p>
&lt;p>To analyse this, you need to use a tool such as &lt;code>top&lt;/code>. Better still, get something a bit more comprehensive such as &lt;code>glances&lt;/code>. Either way, these will tell you how much CPU and memory (RAM) is being used and by what. Start by looking at the three &amp;rsquo;load&amp;rsquo; values, these should all be fairly low, if they are going over about 2-3 regularly then you have an issue.&lt;/p>
&lt;p>Next look at the &amp;lsquo;swap&amp;rsquo;. If this is being used regularly, you will have a performance bottleneck because memory (RAM) is being overused. To fix this, you have to unload some services. If using the &lt;code>glances&lt;/code> tool, it will show a warning if the memory is swapping.&lt;/p>
&lt;p>The easiest way to remove load is likely to be turning off the &amp;lsquo;desktop&amp;rsquo;. This gives you a GUI that you directly interact with via keyboard and monitor. Removing this will remove lots of load on memory and CPU. Have a look at articles that explain how to run your device &amp;lsquo;headless&amp;rsquo;. You will need to be able to connect to your device over the network from another device.&lt;/p>
&lt;p>After that, if there are still issues, you need to look at taking off services that you don&amp;rsquo;t actually need running.&lt;/p>
&lt;p>Finally, if you still have issues, you will need to think about splitting services between multiple devices or using a more powerful device.&lt;/p>
&lt;h1 id="back-end-server">Back End (server)&lt;/h1>
&lt;h2 id="using-nodejs---inspect-option">Using Node.JS &lt;code>--inspect&lt;/code> option&lt;/h2>
&lt;h1 id="front-end-browser-node-red-admin-ui">Front End Browser (Node-RED Admin UI)&lt;/h1>
&lt;p>For any browser performance issues, you firstly need to ensure that the problem is actually coming from something related to Node-RED. So you should turn off any browser extensions before continuing. An extension such as SimpleExtManager for Chromium browsers will assist with easily turning on/off extensions.&lt;/p>
&lt;h2 id="browser-performance-profiling">Browser Performance Profiling&lt;/h2>
&lt;p>Using your browser&amp;rsquo;s developer tools, you are able to record and analyse a performance analysis. The Chromium developer tools have three tabs to help with this. Performance, Memory and Application.&lt;/p>
&lt;p>The Performance tab is perhaps the easiest to get going with. Click on that tab and then start profiling. Leave that for an amount of time that you estimate will let you see any ongoing performance issues. That might be just a few seconds or a few minutes. You will want to tick the &amp;ldquo;memory&amp;rdquo; option and probably don&amp;rsquo;t need the &amp;ldquo;Screenshots&amp;rdquo; option.&lt;/p>
&lt;p>The thing to look at first is likely to be the memory utilisation. There is a graph 1/2 way down the display that shows you some important metrics including the &amp;ldquo;JS Heap&amp;rdquo;. See how big that is getting by hovering over the line. Also look at how fast it is growing. You should see that the heap reduces periodically as the JavaScript engine does a &amp;lsquo;garbage collection&amp;rsquo;.&lt;/p>
&lt;p>You can also do multiple recordings and compare the heap over a longer period.&lt;/p>
&lt;h1 id="front-end-dashboard-uibuilder-http-in-out-nodes-etc">Front End (Dashboard, uibuilder, http-in/-out nodes, etc.)&lt;/h1></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/node-red">Node-RED</category><category domain="https://it.knightnet.org.uk/tags/node.js">Node.JS</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/debugging">Debugging</category><category domain="https://it.knightnet.org.uk/tags/performance">Performance</category></item><item><title>How to take control of JavaScript console output</title><link>https://it.knightnet.org.uk/kb/node-js/smart-console-logging/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/smart-console-logging/</guid><pubDate>Sat, 02 Feb 2019 00:52:46 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/smart-console-logging/</guid><description><div>All browsers have the console object that lets you output to the developer console log. But in production, you don't want this output, only in development. So here is the easiest way I've found to take control.</div><div>&lt;p>This is a simple example and really needs expanding to be more general purpose.&lt;/p>
&lt;p>It uses a global &lt;code>debug&lt;/code> variable to control output. If &lt;code>debug&lt;/code> is false, no output will occur.&lt;/p>
&lt;p>All functions of the console object are taken over by this function.&lt;/p>
&lt;h2 id="code">Code&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/** Debugging function
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @param {string} type One of log|error|warn|info|dir, etc
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @param {...*} msg Msg(s) to send to console
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * WARNING: ...args is ES6, it doesn&amp;#39;t work on IE11
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @since 2019-02-01 Apply any number of args
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> **/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//myDebug = function (type, ...args) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">myDebug&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="nx">debug&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">type&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">arguments&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">//console[type](...args)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">console&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">type&lt;/span>&lt;span class="p">].&lt;/span>&lt;span class="nx">apply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">undefined&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[].&lt;/span>&lt;span class="nx">slice&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">call&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">arguments&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="c1">// --- End of debug function --- //
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>What JavaScript versions are there and how do they map to Node.JS versions?</title><link>https://it.knightnet.org.uk/kb/node-js/javascript-node-versions/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/javascript-node-versions/</guid><pubDate>Fri, 04 Jan 2019 20:03:59 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/javascript-node-versions/</guid><description><div>There are now far too many versions of JavaScript. Worse, there are several ways to refer to a JavaScript version. Then we have Node.JS which has its own versioning. This post tries to summarise it all.</div><div>&lt;p>This is just a summary for my own reference. See &lt;a href="#references">References&lt;/a> below for more details.&lt;/p>
&lt;p>Please let me know if there are any errors. I will update the table periodically.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>ECMA-262 Version&lt;/th>
&lt;th>ECMAScript Year Version&lt;/th>
&lt;th>Publish Date&lt;/th>
&lt;th>Node.JS Version&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>5&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>2009-12&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>6&lt;/td>
&lt;td>ES2015&lt;/td>
&lt;td>2015-06&lt;/td>
&lt;td>6.5.0+&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>7&lt;/td>
&lt;td>ES2016&lt;/td>
&lt;td>2016-06&lt;/td>
&lt;td>7.0.0+&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>8&lt;/td>
&lt;td>ES2017&lt;/td>
&lt;td>2017-06&lt;/td>
&lt;td>8.10.0+&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>9&lt;/td>
&lt;td>ES2018&lt;/td>
&lt;td>2018-06&lt;/td>
&lt;td>10.0.0+&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Notes:&lt;/p>
&lt;ul>
&lt;li>Versions of Node.JS prior to those shown are likely to support &lt;em>some&lt;/em> features of newer JS versions. The versions shown are those that support virtually all of the features.&lt;/li>
&lt;li>Some JavaScript features may not be implemented in Node.JS.&lt;/li>
&lt;li>Node uses the V8 JavaScript engine. Also used by the chromium browser (which underpins Vivaldi, Google Chrome, Opera and many others. Soon to be used by Microsoft Edge as well).&lt;/li>
&lt;/ul>
&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://en.wikipedia.org/wiki/ECMAScript">Wikipedia ECMAScript Article&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kangax.github.io/compat-table/es6/">Kangax&amp;rsquo;s JavaScript Compatability Table&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://node.green/">Node Green&lt;/a> - Maps Node versions to JavaScript versions and shows what is supported in each version. Uses Kangax&amp;rsquo;s table.&lt;/li>
&lt;li>&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">Mozilla Developer Network (MDN)&lt;/a> - Details each aspect of JavaScript as a reference, each page has a compatibility table showing browsers support. Uses Kangax&amp;rsquo;s table.&lt;/li>
&lt;/ul></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category><category domain="https://it.knightnet.org.uk/tags/node.js">node.js</category><category domain="https://it.knightnet.org.uk/tags/nodejs">nodejs</category></item><item><title>How to loop over JavaScript arrays and objects</title><link>https://it.knightnet.org.uk/kb/node-js/looping/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/looping/</guid><pubDate>Fri, 04 Jan 2019 20:00:07 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/looping/</guid><description><div>JavaScript can be a pain at times. Loops are a fundamental part of all computer languages but in JavaScript, there are some oddities. This post is a summary of the different loop features and when to use them. It is likely to be updated from time-to-time as the standards are still changing.</div><div>&lt;p>This is a personal, and incomplete reminder about doing efficient loops in JavaScript.&lt;/p>
&lt;p>Of course, you should generally start with whatever is &lt;em>simplest&lt;/em>. Generally you should not attempt
to optimise too soon.&lt;/p>
&lt;h2 id="arrays">Arrays&lt;/h2>
&lt;h2 id="objects">Objects&lt;/h2>
&lt;p>The old fashioned way still works &amp;amp; is still generally the fastest.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">keys&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="nx">sort&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kd">var&lt;/span> &lt;span class="nx">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="nx">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="nx">keys&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">length&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="nx">i&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">i&lt;/span>&lt;span class="p">]])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Somewhat faster version of the above (the length is not calculated on each loop and prefix iterator is slightly faster than postfix).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">var&lt;/span> &lt;span class="nx">keys&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="nx">sort&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kd">var&lt;/span> &lt;span class="nx">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">len&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">keys&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">length&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="nx">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="nx">len&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="nx">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">i&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">i&lt;/span>&lt;span class="p">]])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>From JS v5, you can use a combination of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">&lt;code>Object.keys()&lt;/code>&lt;/a> and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">&lt;code>Array.prototype.forEach()&lt;/code>&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Object&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">obj&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">forEach&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In addition, &lt;code>Object.values(obj)&lt;/code> does what you&amp;rsquo;d expect.&lt;/p>
&lt;p>&lt;code>for ... in&lt;/code> (&lt;a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...in">MDN&lt;/a>) - includes non-own properties.&lt;/p>
&lt;p>From JS v6 (ES2015), you can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of">&lt;code>for...of&lt;/code>&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">key&lt;/span> &lt;span class="k">of&lt;/span> &lt;span class="nb">Object&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">obj&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">obj&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In JS v8 (ES2017), &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries">&lt;code>Object.entries()&lt;/code>&lt;/a> was added which avoids having to look up each value in the original object.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Object&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">entries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">obj&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">forEach&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">([&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">value&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">value&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Object.keys()&lt;/code> and &lt;code>Object.entries()&lt;/code> iterate properties in the same order as a &lt;code>for...in&lt;/code> loop. However, they &lt;em>ignore the prototype chain&lt;/em>. Only the object&amp;rsquo;s own enumerable properties are iterated.&lt;/p>
&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="http://perfjs.info/test/384A61CA-DA2E-4FD2-A113-080010D4A42B">JSperf Object Iteration Comparison&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://stackoverflow.com/questions/684672/how-do-i-loop-through-or-enumerate-a-javascript-object">How do I loop through or enumerate a JavaScript object? (StackOverflow)&lt;/a>&lt;/li>
&lt;/ul></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>How to get the properties of a JavaScript object without errors</title><link>https://it.knightnet.org.uk/kb/node-js/get-properties/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/get-properties/</guid><pubDate>Thu, 03 Jan 2019 13:53:38 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/get-properties/</guid><description><div>You cannot natively request chained properties of a JavaScript object without the possibility of an error. This utility function allows you to get any properties, no matter how they are nested.</div><div>&lt;p>Let&amp;rsquo;s say that we have an object like that shown in &lt;a href="#example-object">the example&lt;/a>.&lt;/p>
&lt;p>We can use the function to get any property, including nested properties and property names with spaces
very simply. We can use both dot and bracket notation as shown in the tests.&lt;/p>
&lt;p>The function will always either return the value of the given property or &lt;code>undefined&lt;/code>. It will not
return an error.&lt;/p>
&lt;h2 id="example-object">Example Object&lt;/h2>
&lt;p>We can use this for reference&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="s2">&amp;#34;fred&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;b&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="s2">&amp;#34;yup&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;c1&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nt">&amp;#34;c2&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;d&amp;#34;&lt;/span>&lt;span class="p">:{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;d 1&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;d 2&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;d 2a&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="s2">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;d 2b&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="s2">&amp;#34;b&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="code">Code&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/** Get a nested property from an object without returning any errors.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * If the property or property chain doesn&amp;#39;t exist, undefined is returned.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Property names with spaces may use either dot or bracket &amp;#34;[]&amp;#34; notation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Note that bracketed property names without surrounding quotes will fail the lookup.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * e.g. embedded variables are not supported.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @param {object} obj The object to check
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @param {string} prop The property or property chain to get (e.g. obj.prop1.prop1a or obj[&amp;#39;prop1&amp;#39;].prop2)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * @returns {*|undefined} The value of the objects property or undefined if the property doesn&amp;#39;t exist
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">obj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">prop&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">typeof&lt;/span> &lt;span class="nx">obj&lt;/span> &lt;span class="o">!==&lt;/span> &lt;span class="s1">&amp;#39;object&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">throw&lt;/span> &lt;span class="s1">&amp;#39;getProp: obj is not an object&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">typeof&lt;/span> &lt;span class="nx">prop&lt;/span> &lt;span class="o">!==&lt;/span> &lt;span class="s1">&amp;#39;string&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">throw&lt;/span> &lt;span class="s1">&amp;#39;getProp: prop is not a string&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Replace [] notation with dot notation
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">prop&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">prop&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sr">/\[[&amp;#34;&amp;#39;`](.*)[&amp;#34;&amp;#39;`]\]/g&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;.$1&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nx">prop&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">reduce&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">prev&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">curr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nx">prev&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="nx">prev&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">curr&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kc">undefined&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span> &lt;span class="nx">obj&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="nx">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="c1">// --- end of fn getProp() --- //
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="tests">Tests&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">testObj&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="s2">&amp;#34;fred&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;b&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="s2">&amp;#34;yup&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;c1&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;c2&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">},&lt;/span>&lt;span class="s2">&amp;#34;d&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;d 1&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;d 2&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;d 2a&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="s2">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;d 2b&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="s2">&amp;#34;b&amp;#34;&lt;/span>&lt;span class="p">}}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">let&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;b&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="s1">&amp;#39;yup&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected b === &amp;#34;yup&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;e&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;e&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="kc">undefined&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected e === undefined&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;b.b1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;b.b1&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="kc">undefined&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected b.b1 === undefined&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;c&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// console.assert doesn&amp;#39;t seem to work for comparing objects
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//console.assert(x==={&amp;#34;c1&amp;#34;: 1, &amp;#34;c2&amp;#34;: 2}, &amp;#39;Expected c === {c1: 1, c2: 2}&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c.c1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;c.c1&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected c.c1 === 1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c[&amp;#34;c1&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;c[&amp;#34;c1&amp;#34;]&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected c[&amp;#34;c1&amp;#34;] === 1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;d.d 1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;d.d 1&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected d.d 1 === &amp;#34;b&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;d.d 2.d 2b&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;d.d 2.d 2b&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected d.d 2.d 2b === &amp;#34;b&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">getProp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">testObj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;d[&amp;#34;d 2&amp;#34;].d 2b&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="s1">&amp;#39;getProp: &amp;#34;d[&amp;#34;d 2&amp;#34;]d 2b&amp;#34; &amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">x&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">x&lt;/span>&lt;span class="o">===&lt;/span>&lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Expected d[&amp;#34;d 2&amp;#34;]d 2b === &amp;#34;b&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>How to walk through a JavaScript object in sort order</title><link>https://it.knightnet.org.uk/kb/node-js/walk-ordered-object/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/walk-ordered-object/</guid><pubDate>Mon, 31 Dec 2018 13:44:45 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/walk-ordered-object/</guid><description><div>Using a JavaScript object like a keyed array, what is the simplest way to walk through the object?</div><div>&lt;p>Let&amp;rsquo;s say that we have an object like that shown in &lt;a href="#example-object">the example&lt;/a>.&lt;/p>
&lt;p>How do we output the content, ordered by key?&lt;/p>
&lt;p>The code creates an array from the primary keys of the object, sorts the array and then walks
through each entry.&lt;/p>
&lt;h2 id="example-object">Example Object&lt;/h2>
&lt;p>We can use this for reference&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Pi3NR-LIVE&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Pi2NR-LIVE&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;D1M04&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="code">Code&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">myObj&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Pi3NR-LIVE&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Pi2NR-LIVE&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;D1M04&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="s2">&amp;#34;Online&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Object&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">keys&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">myObj&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">sort&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="nx">forEach&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="sb">`&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="sb"> : &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nx">myObj&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nx">key&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="sb">`&lt;/span> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Will output (note the reordering):
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> *
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * D1M04 : Online
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Pi2NR-LIVE : Online
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Pi3NR-LIVE : Online
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> *
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> **/&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>Download a GitHub Repository using Node.JS</title><link>https://it.knightnet.org.uk/kb/node-js/download-repo-github/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/download-repo-github/</guid><pubDate>Sun, 30 Dec 2018 22:03:07 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/download-repo-github/</guid><description><div>Downloading a repository from GitHub using Node.JS should be really easy. But it isn't! This KB post reminds us of the tricks required.</div><div>&lt;p>We have to be careful with the source URL names when working with GitHub as the URL&amp;rsquo;s generally exposed on the web interface
are &lt;strong>not&lt;/strong> the actual URL&amp;rsquo;s. The Node.JS http/https get() functions don&amp;rsquo;t handle redirections well.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="ch">#!/usr/bin/env node
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="ch">&lt;/span>&lt;span class="s1">&amp;#39;use strict&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Install the Node-RED alternate installation template
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> *
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * Author: Julian Knight (Totally Information), Jan. 2019
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> * License: MIT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">fs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;fs&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">https&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">download&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">dest&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">cb&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">file&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">fs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">createWriteStream&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">dest&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">request&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">https&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">response&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">response&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">pipe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">file&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">on&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;finish&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">close&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">cb&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// close() is async, call cb after close completes.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}).&lt;/span>&lt;span class="nx">on&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;error&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">err&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="c1">// Handle errors
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">fs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">unlink&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">dest&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Delete the file async. (But we don&amp;#39;t check the result)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">cb&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nx">cb&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">err&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Download latest archive from GitHub to temp folder
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">dest&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;./alternate-node-red-installer.zip&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://codeload.github.com/TotallyInformation/alternate-node-red-installer/zip/master&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">download&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">dest&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kd">function&lt;/span>&lt;span class="p">(){&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Done&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Obviously, it would be better to add proper error traps and messaging.&lt;/p>
&lt;h2 id="github-urls">GitHub URL&amp;rsquo;s&lt;/h2>
&lt;p>As mentioned, most of the exposed GitHub URL&amp;rsquo;s actually redirect which upsets Node&amp;rsquo;s built-in
get functions. The downside of using the direct URL&amp;rsquo;s is that they may change format from
time-to-time. If you can, use a 3rd-party library such as &lt;a href="https://github.com/request/request">request&lt;/a>
which handles http vs https and redirects without additional programming.&lt;/p>
&lt;p>The format for the actual repository archives (in zipped form) is:&lt;/p>
&lt;p>&lt;code>https://codeload.github.com/&amp;lt;userOrOrgName&amp;gt;/&amp;lt;repoName&amp;gt;/zip/&amp;lt;branch&amp;gt;&lt;/code>&lt;/p>
&lt;p>Where: &lt;code>&amp;lt;branch&amp;gt;&lt;/code> is either &amp;lsquo;master&amp;rsquo; or a git tag ID (e.g. &amp;lsquo;v1.2.3&amp;rsquo;) or other git branch ID.&lt;/p>
&lt;p>For an individual file from the repository, use:&lt;/p>
&lt;p>&lt;code>raw.githubusercontent.com/&amp;lt;userOrOrgName&amp;gt;/&amp;lt;repository&amp;gt;/&amp;lt;branch&amp;gt;/&amp;lt;filename&amp;gt;&lt;/code>&lt;/p>
&lt;p>&lt;a href="https://raw.githubusercontent.com/TotallyInformation/alternate-node-red-installer/">https://raw.githubusercontent.com/TotallyInformation/alternate-node-red-installer/&lt;/a>&lt;/p>
&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/41736280/node-js-does-not-correctly-download-file-from-github-url">Node JS does not correctly download file from github url&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries">How to download a file with Node.js (without using third-party libraries)?&lt;/a>&lt;/li>
&lt;/ul></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/node.js">node.js</category><category domain="https://it.knightnet.org.uk/tags/nodejs">nodejs</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>Node.JS and JavaScript</title><link>https://it.knightnet.org.uk/kb/node-js/</link><guid isPermaLink="true">https://it.knightnet.org.uk/kb/node-js/</guid><pubDate>Sun, 30 Dec 2018 21:58:14 +0000</pubDate><guid>https://it.knightnet.org.uk/kb/node-js/</guid><description><div>Node.JS allows JavaScript to be used as a server-side (back-end) programming language.</div><div>&lt;h2 id="references">References&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://nodejs.org/en/">NodeJS docs and download&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://node.green/">What JavaScript/ECMAscript features does each version of Node.JS support?&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.npmjs.com/">npm docs and module search&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://npms.io/">npms - another module search site&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">MDN JavaScript reference (searchable)&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="knowledgebase-articles">Knowledgebase Articles&lt;/h2></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/tags/node.js">node.js</category><category domain="https://it.knightnet.org.uk/tags/nodejs">nodejs</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category><category domain="https://it.knightnet.org.uk/tags/ecmascript">ECMAscript</category></item><item><title>Diigo Bookmarks 05/12/2011</title><link>https://it.knightnet.org.uk/2011/05/diigo-bookmarks-05122011.html</link><guid isPermaLink="true">https://it.knightnet.org.uk/2011/05/diigo-bookmarks-05122011.html</guid><pubDate>Thu, 12 May 2011 12:31:08 +0000</pubDate><guid>https://it.knightnet.org.uk/2011/05/diigo-bookmarks-05122011.html</guid><description><div/><div>&lt;!-- raw HTML omitted -->
&lt;pre>&lt;code>&amp;lt;p class=&amp;quot;diigo-description&amp;quot;&amp;gt;
&amp;amp;#8220;Jash is a DHTML-based window that gives you command-line JavaScript access to the current browser window. With this console you can quickly debug scripts, manipulate the DOM, view the current page&amp;amp;#8217;s objects, functions, and variables, execute arbitrary Javascript, enter new CSS (in IE, Firefox, Opera, and Safari), and much more.&amp;amp;#8221; &amp;amp;#8211; A useful tool to execute JavaScript, make live (temporary) CSS changes to a page, discover the page structure, etc. for developers. Written totally in JavaScript so can be used on any platform with any browser. Include in your own pages for debugging or load via a bookmarklet to run on any page.
&amp;lt;/p&amp;gt;
&amp;lt;p class=&amp;quot;diigo-tags&amp;quot;&amp;gt;
&amp;lt;span&amp;gt;tags:&amp;lt;/span&amp;gt; &amp;lt;a href=&amp;quot;http://www.diigo.com/user/knightnet/javascript&amp;quot;&amp;gt;javascript&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://www.diigo.com/user/knightnet/programming&amp;quot;&amp;gt;programming&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://www.diigo.com/user/knightnet/development&amp;quot;&amp;gt;development&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://www.diigo.com/user/knightnet/bookmarklet&amp;quot;&amp;gt;bookmarklet&amp;lt;/a&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;ul class=&amp;quot;diigo-comments&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;
Jash is a DHTML-based window that gives you command-line JavaScript access to the current browser window. With this console you can quickly debug scripts, manipulate the DOM, view the current page&amp;amp;#8217;s objects, functions, and variables, trace the execution stack, execute arbitrary Javascript, enter new CSS (in IE or Firefox!), and much more.&amp;lt;span class=&amp;quot;diigo-post-by&amp;quot;&amp;gt; &amp;amp;#8211; post by &amp;lt;a href=&amp;quot;http://www.diigo.com/user/ycc2106&amp;quot;&amp;gt;yc c&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code>&lt;/pre>
&lt;!-- raw HTML omitted --></div></description><author>Julian Knight</author><category domain="https://it.knightnet.org.uk/categories/development">Development</category><category domain="https://it.knightnet.org.uk/categories/diigo">Diigo</category><category domain="https://it.knightnet.org.uk/tags/bookmarklet">Bookmarklet</category><category domain="https://it.knightnet.org.uk/tags/javascript">JavaScript</category></item></channel></rss>