Sometimes I do a code kata at codewars.com. That is a fun way to solve computer science related problems, learn on the way to solve them and especially learn from the solutions of others.

Today I completed the kata “Make a spanning tree” using Javascript. I occasionally use Javascript to write an event handler or so but I don’t have much experience in “modern” Javascript. Here is what I learnt from looking at the solutions of others.

Destructuring

I know this from my Scala class and Clojure.

You can assign array elements to variables:

   
   var a, b, rest;
   [a, b] = [10, 20];
   console.log(a);
   // expected output: 10

   console.log(b);
   // expected output: 20

   [a, b, ...rest] = [10, 20, 30, 40, 50];

   console.log(rest);
   // expected output: [30,40,50]

so “…rest” is assign the rest of the array.

This is nice syntactic sugar also when working with nested arrays. Eg when “edges” is an array of pairs:

   
   // sort edges by weight
   edges.sort(([edge_a, a], [edge_b, b]) => a - b);

There is object destructuring:

   
var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

and even assigning to new variable names

   
var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
 
console.log(foo); // 42 
console.log(bar); // true   

See MDN web docs for more.

Spread operator to create an array using an array literal

Using an array literal to create an array from two other arrays:

  
   const sets = {};
   //...
   // new array with sets[a] elements and sets[b] elements
   const set = [...sets[a], ...sets[b]];

Objects are associative arrays (aka Maps)

Although I already knew this, kind of, this refreshes my JS
knowledge.

First, you can add properties to Objects without declaring them in
the first place:

  
   let obj = {}; // anonymous object
   obj.height=2; // create new property "heigth" and assign value
   console.log(obj.height); // 2
   

Second, instead of the dot-notation you can use array index
notation using the property name as the index:

  
   let ojb = {};
   obj['height'] = 2;
   console.log(obj['height']); // 2
   

One solution uses this in order to save the weighted edges in an
object just like i did in the proper Map object:

  
   let set = {};
   edges.filter(e => e[0][1] !== e[0][0]).forEach(e => {
    if (!set[e[0]] || minOrMaxFunc(set[e[0]], e[1])>00) { set[e[0]] = e[1]; }
   });
   

Third, methods are kind of properties, too. In the same solution,
“minOrMaxFunc” is cleverly choosen (“minOrMax” argument is either
“min” or “max”):

  
   function makeSpanningTree(edges, minOrMax) {
     let minOrMaxFunc = { min: (a, b) => a - b, max: (a, b) => b - a }[minOrMax];
     // ...
   }
   

it creates an objects with two methods: “min” and “max” and then
accesses the one that is given in the argument. If “minOrMax” is
“min”, a reference of the “min” method is returned.

Strings are arrays

Destructuring works with strings:

  
   let [a,b] = 'ABC';
   console.log(a); // "A"
   console.log(b); // "B"

and you can index strings:

  
   const s = "ABC";
   s[1]; // "B"

“var” vs. “let”

Of course, the solutions written in “modern” JS use “let” and
“const” all over the place. I just reassured myself about the
difference between let and var:

First, variables declared in a block using “var” are visible
outside that block and are “known” before being declared:

  
   function f() {
    console.log(v); // undefined
    { var v = 3; }
    console.log(v); // 3
   }
   

a block might be a for-loop.

Variables declared using let are not visible outside the block and
are not “known” before declared:

  
   function f() {
    console.log(v); // Reference error
    { let v = 3; }
    console.log(v); // Reference error
   }   
   

Third, you might not redeclare a variable using let:

  
   var a = 0;
   var a = 1; // OK
   let b = 0;
   let b = 1; // not OK
   

So basically, “let” is a sane way to declare variables.