Tuesday, June 27, 2017

Javascript Shortcuts

Creating a new function as shown in the receive function in the first clock of code creates a new lexical scope, a new 'this', which necessitates 'var that = this;'.

Lambdas do not create a new lexical scope, ie, lexical scope is retained when using lambdas.

Old Style

Old style Javascript without lambdas requires use of that = this;.
let screenObj = {
  name: "Button",

  handleMessage: function(message, handler) {
   handler(message);
  },

  receive: function(greeting) {
    var that = this;
    this.handleMessage(greeting, function(message) {
      console.log(message + that.name)
    })
  }
};

screenObj.receive("Hello, ");  // Hello, Button
Eliminate that = this; code and avoid having to deal with changes to lexical scope by using lambdas.
Replace function(message) with message => to define the lambda.
let screenObj = {
  name: "Button",

  handleMessage: function(message, handler) { handler(message)},

  receive: function(greeting) {
    this.handleMessage(greeting, 
     message => console.log(message + this.name))
  }
};

screenObj.receive("Hello, ");    // Hello, Button

Simplifying

let first = 'Johnnie'
let last = 'Cash'

// this definition can be simplified
const firstAndLast = { first: first, last: last }
console.log(firstAndLast.last)    // Cash

// name only the keys
const firstLast = { first, last }
console.log(firstLast.last)      // Cash

Spread Operator

const odd = [1, 3, 5];
const even = [2, 4, 6];
const nums = [...even, ...odd]; // [2, 4, 6, 1, 3, 5]

The Import Statement

const foo = require('blah/foo');
const bar = require('blah/bar');

// can be replaced with

import {foo, bar} from 'blah';

Default Parameters

let noDefaults = function(greeting, name) {
  console.log(`${greeting}, ${name}`);
}
let withDefaults = function(greeting="Hello", name="George") {
  console.log(`${greeting}, ${name}`);
}
noDefaults();               // undefined, undefined
withDefaults("Hi", "Joe");  // Hi, Joe
withDefaults();             // Hello, George

Destructuring an Array

let names = ['Charles', 'Debbie', 'Susan', 'Keith']
var [boy1,,,boy2] = names
console.log(boy1)  // Charles
console.log(boy2)  // Keith

Destructuring an Object

let managerie = () => {
  return {
    dog: 'terrier',
    cat: 'tabby',
    fish: 'shark',
    bird: 'parrot',
  }
};

let {dog, fish} = managerie();
console.log(dog);   // terrier
console.log(fish);  // shark

Destructuring an Object in the Argument List

let sneakers = [
  {
    name: 'Air Jordans',
    brand: 'Nike',
  },
  {
    name: 'Flyers',
    brand: 'Converse',
  },
  {
    name: 'Runners',
    brand: 'Sketchers',
  },
  {
    name: 'Trail Runner',
    brand: 'New Balance',
  }];

let [,,cheapShoe] = sneakers
let log = function({brand}) { // destructure the object passed
  console.log(brand) 
}
log(cheapShoe)    // Sketchers

ES6 Generators

function*, yield and next()
function* repeat() {
  const arr = ["A", "B", "C", "D"];
  for (let x in arr) {
  yield arr[x];
  }
}

var foo = repeat();
let bar = foo.next();
while (!bar.done) {
  console.log(bar.value); // logs a letter with each iteration 
  bar = foo.next();
}

The Array.reduce Function

let votes=['react','react','react','vue','meteor','angular','angular']
let voteCount = function(tally, vote) {
  if (!tally[vote]) {
    tally[vote] = 1
  } else {
    tally[vote] += 1
  }
  return tally
}
let results = votes.reduce(voteCount, {})
for (framework in results) {
  console.log(framework + "=" + results[framework])
}

// react=3
// vue=1
// meteor=1
// angular=2

Map and Reduce

const data = ["a", "b","c"]
let doubled = data.reduce(function(acc, elem) {
  acc.push(elem + elem)
  return acc;
}, []);

let doubleMapped = data.map(function(elem) {
  return elem + elem;
});

let filterMapped = data.filter(function(elem) {
  return elem !== "b";
}).map(function(elem) {
 return elem + elem.toUpperCase();
});

console.log(doubled)      // [aa,bb,cc]
console.log(doubleMapped) // [aa,bb,cc]
console.log(filterMapped) // [aA,cC]